diff options
| -rw-r--r-- | compiler/rustc_middle/src/util/find_self_call.rs | 41 | ||||
| -rw-r--r-- | tests/ui/lint/lint-const-item-mutation.stderr | 7 |
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 | |
