about summary refs log tree commit diff
path: root/compiler/rustc_lint/src/noop_method_call.rs
diff options
context:
space:
mode:
authorEsteban Küber <esteban@kuber.com.ar>2021-01-12 18:37:32 -0800
committerRyan Levick <me@ryanlevick.com>2021-03-03 11:22:56 +0100
commite48670c34a3f5ab3fe9defcc61861999f3f14e93 (patch)
treea082d55e96c082b3bf163f7aaecd56c6b4b077bf /compiler/rustc_lint/src/noop_method_call.rs
parent49f32e0c8e78948210654299a8c19b2e0f0cbfa9 (diff)
downloadrust-e48670c34a3f5ab3fe9defcc61861999f3f14e93.tar.gz
rust-e48670c34a3f5ab3fe9defcc61861999f3f14e93.zip
Increase accuracy of lint trigger
Diffstat (limited to 'compiler/rustc_lint/src/noop_method_call.rs')
-rw-r--r--compiler/rustc_lint/src/noop_method_call.rs58
1 files changed, 35 insertions, 23 deletions
diff --git a/compiler/rustc_lint/src/noop_method_call.rs b/compiler/rustc_lint/src/noop_method_call.rs
index 1aa4a986cd1..04d87dc9592 100644
--- a/compiler/rustc_lint/src/noop_method_call.rs
+++ b/compiler/rustc_lint/src/noop_method_call.rs
@@ -62,33 +62,45 @@ impl<'tcx> LateLintPass<'tcx> for NoopMethodCall {
                         // Resolve the trait method instance
                         if let Ok(Some(i)) = ty::Instance::resolve(cx.tcx, param_env, did, substs) {
                             // Check that it implements the noop diagnostic
-                            if [
-                                sym::noop_method_borrow,
-                                sym::noop_method_clone,
-                                sym::noop_method_deref,
+                            for (s, peel_ref) in [
+                                (sym::noop_method_borrow, true),
+                                (sym::noop_method_clone, false),
+                                (sym::noop_method_deref, true),
                             ]
                             .iter()
-                            .any(|s| cx.tcx.is_diagnostic_item(*s, i.def_id()))
                             {
-                                let method = &call.ident.name;
-                                let receiver = &elements[0];
-                                let receiver_ty = cx.typeck_results().expr_ty(receiver);
-                                let expr_span = expr.span;
-                                let note = format!(
-                                    "the type `{:?}` which `{}` is being called on is the same as the type returned from `{}`, \
-                                        so the method call does not do anything and can be removed.",
-                                    receiver_ty, method, method
-                                );
-
-                                let span = expr_span.with_lo(receiver.span.hi());
-                                cx.struct_span_lint(NOOP_METHOD_CALL, span, |lint| {
+                                if cx.tcx.is_diagnostic_item(*s, i.def_id()) {
                                     let method = &call.ident.name;
-                                    let message = format!("call to `.{}()` on a reference in this situation does nothing", &method);
-                                    lint.build(&message)
-                                        .span_label(span, "unnecessary method call")
-                                        .note(&note)
-                                        .emit()
-                                });
+                                    let receiver = &elements[0];
+                                    let receiver_ty = cx.typeck_results().expr_ty(receiver);
+                                    let receiver_ty = match receiver_ty.kind() {
+                                        // Remove one borrow from the receiver as all the trait methods
+                                        // we care about here have a `&self` receiver.
+                                        ty::Ref(_, ty, _) if *peel_ref => ty,
+                                        _ => receiver_ty,
+                                    };
+                                    let expr_ty = cx.typeck_results().expr_ty_adjusted(expr);
+                                    if receiver_ty != expr_ty {
+                                        return;
+                                    }
+                                    let expr_span = expr.span;
+                                    let note = format!(
+                                        "the type `{:?}` which `{}` is being called on is the same as \
+                                        the type returned from `{}`, so the method call does not do \
+                                        anything and can be removed",
+                                        receiver_ty, method, method,
+                                    );
+
+                                    let span = expr_span.with_lo(receiver.span.hi());
+                                    cx.struct_span_lint(NOOP_METHOD_CALL, span, |lint| {
+                                        let method = &call.ident.name;
+                                        let message = format!("call to `.{}()` on a reference in this situation does nothing", &method);
+                                        lint.build(&message)
+                                            .span_label(span, "unnecessary method call")
+                                            .note(&note)
+                                            .emit()
+                                     });
+                                }
                             }
                         }
                     }