Auto merge of #116520 - Enselic:large-copy-into-fn, r=oli-obk
large_assignments: Lint on specific large args passed to functions Requires lowering function call arg spans down to MIR, which is done in the second commit. Part of #83518 Also see * https://rust-lang.zulipchat.com/#narrow/stream/182449-t-compiler.2Fhelp/topic/arg.20Spans.20for.20TerminatorKind.3A.3ACall.3F * https://rust-lang.zulipchat.com/#narrow/stream/122651-general/topic/move_size_limit.20lint r? `@oli-obk` (E-mentor)
This commit is contained in:
commit
92f2e0aa62
52 changed files with 379 additions and 210 deletions
|
@ -785,7 +785,7 @@ impl<'tcx> TerminatorKind<'tcx> {
|
|||
Call { func, args, destination, .. } => {
|
||||
write!(fmt, "{destination:?} = ")?;
|
||||
write!(fmt, "{func:?}(")?;
|
||||
for (index, arg) in args.iter().enumerate() {
|
||||
for (index, arg) in args.iter().map(|a| &a.node).enumerate() {
|
||||
if index > 0 {
|
||||
write!(fmt, ", ")?;
|
||||
}
|
||||
|
|
|
@ -16,6 +16,7 @@ use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece};
|
|||
use rustc_hir::def_id::DefId;
|
||||
use rustc_hir::{self, CoroutineKind};
|
||||
use rustc_index::IndexVec;
|
||||
use rustc_span::source_map::Spanned;
|
||||
use rustc_target::abi::{FieldIdx, VariantIdx};
|
||||
|
||||
use rustc_ast::Mutability;
|
||||
|
@ -673,7 +674,9 @@ pub enum TerminatorKind<'tcx> {
|
|||
/// These are owned by the callee, which is free to modify them.
|
||||
/// This allows the memory occupied by "by-value" arguments to be
|
||||
/// reused across function calls without duplicating the contents.
|
||||
args: Vec<Operand<'tcx>>,
|
||||
/// The span for each arg is also included
|
||||
/// (e.g. `a` and `b` in `x.foo(a, b)`).
|
||||
args: Vec<Spanned<Operand<'tcx>>>,
|
||||
/// Where the returned value will be written
|
||||
destination: Place<'tcx>,
|
||||
/// Where to go after this call returns. If none, the call necessarily diverges.
|
||||
|
|
|
@ -229,6 +229,18 @@ impl<'tcx> Operand<'tcx> {
|
|||
Operand::Constant(c) => c.const_.ty(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn span<D: ?Sized>(&self, local_decls: &D) -> Span
|
||||
where
|
||||
D: HasLocalDecls<'tcx>,
|
||||
{
|
||||
match self {
|
||||
&Operand::Copy(ref l) | &Operand::Move(ref l) => {
|
||||
local_decls.local_decls()[l.local].source_info.span
|
||||
}
|
||||
Operand::Constant(c) => c.span,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> BinOp {
|
||||
|
|
|
@ -524,7 +524,7 @@ macro_rules! make_mir_visitor {
|
|||
} => {
|
||||
self.visit_operand(func, location);
|
||||
for arg in args {
|
||||
self.visit_operand(arg, location);
|
||||
self.visit_operand(&$($mutability)? arg.node, location);
|
||||
}
|
||||
self.visit_place(
|
||||
destination,
|
||||
|
|
|
@ -9,6 +9,7 @@ use crate::ty::print::{with_no_trimmed_paths, FmtPrinter, Printer};
|
|||
use crate::ty::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitor};
|
||||
use crate::ty::{self, AliasTy, InferConst, Lift, Term, TermKind, Ty, TyCtxt};
|
||||
use rustc_hir::def::Namespace;
|
||||
use rustc_span::source_map::Spanned;
|
||||
use rustc_target::abi::TyAndLayout;
|
||||
use rustc_type_ir::{ConstKind, DebugWithInfcx, InferCtxtLike, WithInfcx};
|
||||
|
||||
|
@ -819,3 +820,27 @@ impl<'tcx> TypeVisitable<TyCtxt<'tcx>> for TyAndLayout<'tcx, Ty<'tcx>> {
|
|||
visitor.visit_ty(self.ty)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx, T: TypeVisitable<TyCtxt<'tcx>> + Debug + Clone> TypeVisitable<TyCtxt<'tcx>>
|
||||
for Spanned<T>
|
||||
{
|
||||
fn visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
|
||||
self.node.visit_with(visitor)?;
|
||||
self.span.visit_with(visitor)?;
|
||||
ControlFlow::Continue(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx, T: TypeFoldable<TyCtxt<'tcx>> + Debug + Clone> TypeFoldable<TyCtxt<'tcx>>
|
||||
for Spanned<T>
|
||||
{
|
||||
fn try_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>(
|
||||
self,
|
||||
folder: &mut F,
|
||||
) -> Result<Self, F::Error> {
|
||||
Ok(Spanned {
|
||||
node: self.node.try_fold_with(folder)?,
|
||||
span: self.span.try_fold_with(folder)?,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@ use crate::mir::*;
|
|||
use crate::ty::GenericArgsRef;
|
||||
use crate::ty::{self, TyCtxt};
|
||||
use rustc_span::def_id::DefId;
|
||||
use rustc_span::source_map::Spanned;
|
||||
|
||||
/// 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
|
||||
|
@ -23,7 +24,13 @@ pub fn find_self_call<'tcx>(
|
|||
tcx.opt_associated_item(def_id)
|
||||
{
|
||||
debug!("find_self_call: args={:?}", fn_args);
|
||||
if let [Operand::Move(self_place) | Operand::Copy(self_place), ..] = **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));
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue