1
Fork 0

Auto merge of #110405 - fee1-dead-contrib:rollup-9rkree6, r=fee1-dead

Rollup of 4 pull requests

Successful merges:

 - #110397 (Move some utils out of `rustc_const_eval`)
 - #110398 (use matches! macro in more places)
 - #110400 (more clippy fixes: clippy::{iter_cloned_collect, unwarp_or_else_defau…)
 - #110402 (Remove the loop in `Align::from_bytes`)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2023-04-16 13:12:53 +00:00
commit 8a778ca1e3
33 changed files with 91 additions and 114 deletions

View file

@ -99,13 +99,9 @@ pub mod mir;
pub mod thir;
pub mod traits;
pub mod ty;
pub mod util;
mod values;
pub mod util {
pub mod bug;
pub mod common;
}
// Allows macros to refer to this crate as `::rustc_middle`
extern crate self as rustc_middle;

View file

@ -0,0 +1,137 @@
//! Common logic for borrowck use-after-move errors when moved into a `fn(self)`,
//! as well as errors when attempting to call a non-const function in a const
//! context.
use crate::ty::subst::SubstsRef;
use crate::ty::{AssocItemContainer, Instance, ParamEnv, Ty, TyCtxt};
use rustc_hir::def_id::DefId;
use rustc_hir::{lang_items, LangItem};
use rustc_span::symbol::Ident;
use rustc_span::{sym, DesugaringKind, Span};
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub enum CallDesugaringKind {
/// for _ in x {} calls x.into_iter()
ForLoopIntoIter,
/// x? calls x.branch()
QuestionBranch,
/// x? calls type_of(x)::from_residual()
QuestionFromResidual,
/// try { ..; x } calls type_of(x)::from_output(x)
TryBlockFromOutput,
}
impl CallDesugaringKind {
pub fn trait_def_id(self, tcx: TyCtxt<'_>) -> DefId {
match self {
Self::ForLoopIntoIter => tcx.get_diagnostic_item(sym::IntoIterator).unwrap(),
Self::QuestionBranch | Self::TryBlockFromOutput => {
tcx.require_lang_item(LangItem::Try, None)
}
Self::QuestionFromResidual => tcx.get_diagnostic_item(sym::FromResidual).unwrap(),
}
}
}
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub enum CallKind<'tcx> {
/// A normal method call of the form `receiver.foo(a, b, c)`
Normal {
self_arg: Option<Ident>,
desugaring: Option<(CallDesugaringKind, Ty<'tcx>)>,
method_did: DefId,
method_substs: SubstsRef<'tcx>,
},
/// A call to `Fn(..)::call(..)`, desugared from `my_closure(a, b, c)`
FnCall { fn_trait_id: DefId, self_ty: Ty<'tcx> },
/// A call to an operator trait, desugared from operator syntax (e.g. `a << b`)
Operator { self_arg: Option<Ident>, trait_id: DefId, self_ty: Ty<'tcx> },
DerefCoercion {
/// The `Span` of the `Target` associated type
/// in the `Deref` impl we are using.
deref_target: Span,
/// The type `T::Deref` we are dereferencing to
deref_target_ty: Ty<'tcx>,
self_ty: Ty<'tcx>,
},
}
pub fn call_kind<'tcx>(
tcx: TyCtxt<'tcx>,
param_env: ParamEnv<'tcx>,
method_did: DefId,
method_substs: SubstsRef<'tcx>,
fn_call_span: Span,
from_hir_call: bool,
self_arg: Option<Ident>,
) -> CallKind<'tcx> {
let parent = tcx.opt_associated_item(method_did).and_then(|assoc| {
let container_id = assoc.container_id(tcx);
match assoc.container {
AssocItemContainer::ImplContainer => tcx.trait_id_of_impl(container_id),
AssocItemContainer::TraitContainer => Some(container_id),
}
});
let fn_call = parent.and_then(|p| {
lang_items::FN_TRAITS.iter().filter_map(|&l| tcx.lang_items().get(l)).find(|&id| id == p)
});
let operator = if !from_hir_call && let Some(p) = parent {
lang_items::OPERATORS.iter().filter_map(|&l| tcx.lang_items().get(l)).find(|&id| id == p)
} else {
None
};
let is_deref = !from_hir_call && tcx.is_diagnostic_item(sym::deref_method, method_did);
// Check for a 'special' use of 'self' -
// an FnOnce call, an operator (e.g. `<<`), or a
// deref coercion.
let kind = if let Some(trait_id) = fn_call {
Some(CallKind::FnCall { fn_trait_id: trait_id, self_ty: method_substs.type_at(0) })
} else if let Some(trait_id) = operator {
Some(CallKind::Operator { self_arg, trait_id, self_ty: method_substs.type_at(0) })
} else if is_deref {
let deref_target = tcx.get_diagnostic_item(sym::deref_target).and_then(|deref_target| {
Instance::resolve(tcx, param_env, deref_target, method_substs).transpose()
});
if let Some(Ok(instance)) = deref_target {
let deref_target_ty = instance.ty(tcx, param_env);
Some(CallKind::DerefCoercion {
deref_target: tcx.def_span(instance.def_id()),
deref_target_ty,
self_ty: method_substs.type_at(0),
})
} else {
None
}
} else {
None
};
kind.unwrap_or_else(|| {
// This isn't a 'special' use of `self`
debug!(?method_did, ?fn_call_span);
let desugaring = if Some(method_did) == tcx.lang_items().into_iter_fn()
&& fn_call_span.desugaring_kind() == Some(DesugaringKind::ForLoop)
{
Some((CallDesugaringKind::ForLoopIntoIter, method_substs.type_at(0)))
} else if fn_call_span.desugaring_kind() == Some(DesugaringKind::QuestionMark) {
if Some(method_did) == tcx.lang_items().branch_fn() {
Some((CallDesugaringKind::QuestionBranch, method_substs.type_at(0)))
} else if Some(method_did) == tcx.lang_items().from_residual_fn() {
Some((CallDesugaringKind::QuestionFromResidual, method_substs.type_at(0)))
} else {
None
}
} else if Some(method_did) == tcx.lang_items().from_output_fn()
&& fn_call_span.desugaring_kind() == Some(DesugaringKind::TryBlock)
{
Some((CallDesugaringKind::TryBlockFromOutput, method_substs.type_at(0)))
} else {
None
};
CallKind::Normal { self_arg, desugaring, method_did, method_substs }
})
}

View file

@ -0,0 +1,36 @@
use crate::mir::*;
use crate::ty::subst::SubstsRef;
use crate::ty::{self, TyCtxt};
use rustc_span::def_id::DefId;
/// 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, SubstsRef<'tcx>)> {
debug!("find_self_call(local={:?}): terminator={:?}", local, &body[block].terminator);
if let Some(Terminator { kind: TerminatorKind::Call { func, args, .. }, .. }) =
&body[block].terminator
{
debug!("find_self_call: func={:?}", func);
if let Operand::Constant(box Constant { literal, .. }) = func {
if let ty::FnDef(def_id, substs) = *literal.ty().kind() {
if let Some(ty::AssocItem { fn_has_self_parameter: true, .. }) =
tcx.opt_associated_item(def_id)
{
debug!("find_self_call: args={:?}", args);
if let [Operand::Move(self_place) | Operand::Copy(self_place), ..] = **args {
if self_place.as_local() == Some(local) {
return Some((def_id, substs));
}
}
}
}
}
}
None
}

View file

@ -0,0 +1,7 @@
pub mod bug;
pub mod call_kind;
pub mod common;
pub mod find_self_call;
pub use call_kind::{call_kind, CallDesugaringKind, CallKind};
pub use find_self_call::find_self_call;