1
Fork 0

Move find_self_call.

It's a function that does stuff with MIR and yet it weirdly has its own
module in `rustc_middle::util`. This commit moves it into
`rustc_middle::mir`, a more sensible home.
This commit is contained in:
Nicholas Nethercote 2025-01-31 09:55:55 +11:00
parent 3f5e218581
commit 140817380c
6 changed files with 48 additions and 60 deletions

View file

@ -3777,7 +3777,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
let tcx = self.infcx.tcx;
if let Some(Terminator { kind: TerminatorKind::Call { call_source, fn_span, .. }, .. }) =
&self.body[loan.reserve_location.block].terminator
&& let Some((method_did, method_args)) = rustc_middle::util::find_self_call(
&& let Some((method_did, method_args)) = mir::find_self_call(
tcx,
self.body,
loan.assigned_place.local,

View file

@ -17,7 +17,7 @@ use rustc_middle::mir::tcx::PlaceTy;
use rustc_middle::mir::{
AggregateKind, CallSource, ConstOperand, ConstraintCategory, FakeReadCause, Local, LocalInfo,
LocalKind, Location, Operand, Place, PlaceRef, ProjectionElem, Rvalue, Statement,
StatementKind, Terminator, TerminatorKind,
StatementKind, Terminator, TerminatorKind, find_self_call,
};
use rustc_middle::ty::print::Print;
use rustc_middle::ty::{self, Ty, TyCtxt};
@ -1016,12 +1016,9 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
kind: TerminatorKind::Call { fn_span, call_source, .. }, ..
}) = &self.body[location.block].terminator
{
let Some((method_did, method_args)) = rustc_middle::util::find_self_call(
self.infcx.tcx,
self.body,
target_temp,
location.block,
) else {
let Some((method_did, method_args)) =
find_self_call(self.infcx.tcx, self.body, target_temp, location.block)
else {
return normal_ret;
};

View file

@ -27,7 +27,7 @@ use rustc_macros::{HashStable, TyDecodable, TyEncodable, TypeFoldable, TypeVisit
use rustc_serialize::{Decodable, Encodable};
use rustc_span::source_map::Spanned;
use rustc_span::{DUMMY_SP, Span, Symbol};
use tracing::trace;
use tracing::{debug, trace};
pub use self::query::*;
use self::visit::TyContext;
@ -1796,6 +1796,47 @@ impl DefLocation {
}
}
/// Checks if the specified `local` is used as the `self` parameter of a method call
/// in the provided `BasicBlock`. If it is, then the `DefId` of the called method is
/// returned.
pub fn find_self_call<'tcx>(
tcx: TyCtxt<'tcx>,
body: &Body<'tcx>,
local: Local,
block: BasicBlock,
) -> Option<(DefId, GenericArgsRef<'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
{
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));
}
}
}
None
}
// Some nodes are used a lot. Make sure they don't unintentionally get bigger.
#[cfg(target_pointer_width = "64")]
mod size_asserts {

View file

@ -1,47 +0,0 @@
use rustc_span::def_id::DefId;
use rustc_span::source_map::Spanned;
use tracing::debug;
use crate::mir::*;
use crate::ty::{self, GenericArgsRef, TyCtxt};
/// Checks if the specified `local` is used as the `self` parameter of a method call
/// in the provided `BasicBlock`. If it is, then the `DefId` of the called method is
/// returned.
pub fn find_self_call<'tcx>(
tcx: TyCtxt<'tcx>,
body: &Body<'tcx>,
local: Local,
block: BasicBlock,
) -> Option<(DefId, GenericArgsRef<'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
{
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));
}
}
}
None
}

View file

@ -1,8 +1,5 @@
pub mod bug;
pub mod common;
pub mod find_self_call;
pub use find_self_call::find_self_call;
#[derive(Default, Copy, Clone)]
pub struct Providers {

View file

@ -133,7 +133,7 @@ impl<'tcx> Visitor<'tcx> for ConstMutationChecker<'_, 'tcx> {
// the `self` parameter of a method call (as the terminator of our current
// BasicBlock). If so, we emit a more specific lint.
let method_did = self.target_local.and_then(|target_local| {
rustc_middle::util::find_self_call(self.tcx, self.body, target_local, loc.block)
find_self_call(self.tcx, self.body, target_local, loc.block)
});
let lint_loc =
if method_did.is_some() { self.body.terminator_loc(loc.block) } else { loc };