about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_middle/src/util/find_self_call.rs41
-rw-r--r--tests/ui/lint/lint-const-item-mutation.stderr7
2 files changed, 28 insertions, 20 deletions
diff --git a/compiler/rustc_middle/src/util/find_self_call.rs b/compiler/rustc_middle/src/util/find_self_call.rs
index ec6051d0a77..0fdd3520738 100644
--- a/compiler/rustc_middle/src/util/find_self_call.rs
+++ b/compiler/rustc_middle/src/util/find_self_call.rs
@@ -17,26 +17,29 @@ pub fn find_self_call<'tcx>(
     debug!("find_self_call(local={:?}): terminator={:?}", local, body[block].terminator);
     if let Some(Terminator { kind: TerminatorKind::Call { func, args, .. }, .. }) =
         &body[block].terminator
+        && let Operand::Constant(box ConstOperand { const_, .. }) = func
+        && let ty::FnDef(def_id, fn_args) = *const_.ty().kind()
+        && let Some(ty::AssocItem { fn_has_self_parameter: true, .. }) =
+            tcx.opt_associated_item(def_id)
+        && let [Spanned { node: Operand::Move(self_place) | Operand::Copy(self_place), .. }, ..] =
+            **args
     {
-        debug!("find_self_call: func={:?}", func);
-        if let Operand::Constant(box ConstOperand { const_, .. }) = func {
-            if let ty::FnDef(def_id, fn_args) = *const_.ty().kind() {
-                if let Some(ty::AssocItem { fn_has_self_parameter: true, .. }) =
-                    tcx.opt_associated_item(def_id)
-                {
-                    debug!("find_self_call: args={:?}", fn_args);
-                    if let [
-                        Spanned {
-                            node: Operand::Move(self_place) | Operand::Copy(self_place), ..
-                        },
-                        ..,
-                    ] = **args
-                    {
-                        if self_place.as_local() == Some(local) {
-                            return Some((def_id, fn_args));
-                        }
-                    }
-                }
+        if self_place.as_local() == Some(local) {
+            return Some((def_id, fn_args));
+        }
+
+        // Handle the case where `self_place` gets reborrowed.
+        // This happens when the receiver is `&T`.
+        for stmt in &body[block].statements {
+            if let StatementKind::Assign(box (place, rvalue)) = &stmt.kind
+                && let Some(reborrow_local) = place.as_local()
+                && self_place.as_local() == Some(reborrow_local)
+                && let Rvalue::Ref(_, _, deref_place) = rvalue
+                && let PlaceRef { local: deref_local, projection: [ProjectionElem::Deref] } =
+                    deref_place.as_ref()
+                && deref_local == local
+            {
+                return Some((def_id, fn_args));
             }
         }
     }
diff --git a/tests/ui/lint/lint-const-item-mutation.stderr b/tests/ui/lint/lint-const-item-mutation.stderr
index 747c38b8007..0e405c306fe 100644
--- a/tests/ui/lint/lint-const-item-mutation.stderr
+++ b/tests/ui/lint/lint-const-item-mutation.stderr
@@ -75,10 +75,15 @@ warning: taking a mutable reference to a `const` item
   --> $DIR/lint-const-item-mutation.rs:42:5
    |
 LL |     (&mut MY_STRUCT).use_mut();
-   |     ^^^^^^^^^^^^^^^^
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: each usage of a `const` item creates a new temporary
    = note: the mutable reference will refer to this temporary, not the original `const` item
+note: mutable reference created due to call to this method
+  --> $DIR/lint-const-item-mutation.rs:9:5
+   |
+LL |     fn use_mut(&mut self) {}
+   |     ^^^^^^^^^^^^^^^^^^^^^
 note: `const` item defined here
   --> $DIR/lint-const-item-mutation.rs:27:1
    |