//! Borrow checker diagnostics.
+use rustc_const_eval::util::call_kind;
use rustc_errors::DiagnosticBuilder;
use rustc_hir as hir;
use rustc_hir::def::Namespace;
use rustc_hir::def_id::DefId;
-use rustc_hir::lang_items::LangItemGroup;
use rustc_hir::GeneratorKind;
use rustc_middle::mir::{
AggregateKind, Constant, FakeReadCause, Field, Local, LocalInfo, LocalKind, Location, Operand,
use rustc_middle::ty::print::Print;
use rustc_middle::ty::{self, DefIdTree, Instance, Ty, TyCtxt};
use rustc_mir_dataflow::move_paths::{InitLocation, LookupResult};
-use rustc_span::{hygiene::DesugaringKind, symbol::sym, Span};
+use rustc_span::{symbol::sym, Span};
use rustc_target::abi::VariantIdx;
use super::borrow_set::BorrowData;
crate use outlives_suggestion::OutlivesSuggestionBuilder;
crate use region_errors::{ErrorConstraintInfo, RegionErrorKind, RegionErrors};
crate use region_name::{RegionName, RegionNameSource};
-use rustc_span::symbol::Ident;
+crate use rustc_const_eval::util::CallKind;
pub(super) struct IncludingDowncast(pub(super) bool);
match place {
PlaceRef { local, projection: [] } => {
let local = &self.body.local_decls[local];
- self.describe_field_from_ty(&local.ty, field, None)
+ self.describe_field_from_ty(local.ty, field, None)
}
PlaceRef { local, projection: [proj_base @ .., elem] } => match elem {
ProjectionElem::Deref => {
}
ProjectionElem::Downcast(_, variant_index) => {
let base_ty = place.ty(self.body, self.infcx.tcx).ty;
- self.describe_field_from_ty(&base_ty, field, Some(*variant_index))
+ self.describe_field_from_ty(base_ty, field, Some(*variant_index))
}
ProjectionElem::Field(_, field_type) => {
- self.describe_field_from_ty(&field_type, field, None)
+ self.describe_field_from_ty(*field_type, field, None)
}
ProjectionElem::Index(..)
| ProjectionElem::ConstantIndex { .. }
) -> String {
if ty.is_box() {
// If the type is a box, the field is described from the boxed type
- self.describe_field_from_ty(&ty.boxed_ty(), field, variant_index)
+ self.describe_field_from_ty(ty.boxed_ty(), field, variant_index)
} else {
match *ty.kind() {
ty::Adt(def, _) => {
} else {
def.non_enum_variant()
};
- variant.fields[field.index()].ident.to_string()
+ variant.fields[field.index()].name.to_string()
}
ty::Tuple(_) => field.index().to_string(),
ty::Ref(_, ty, _) | ty::RawPtr(ty::TypeAndMut { ty, .. }) => {
- self.describe_field_from_ty(&ty, field, variant_index)
+ self.describe_field_from_ty(ty, field, variant_index)
}
ty::Array(ty, _) | ty::Slice(ty) => {
- self.describe_field_from_ty(&ty, field, variant_index)
+ self.describe_field_from_ty(ty, field, variant_index)
}
ty::Closure(def_id, _) | ty::Generator(def_id, _, _) => {
// We won't be borrowck'ing here if the closure came from another crate,
// We need to add synthesized lifetimes where appropriate. We do
// this by hooking into the pretty printer and telling it to label the
// lifetimes without names with the value `'0`.
- match ty.kind() {
- ty::Ref(
- ty::RegionKind::ReLateBound(_, ty::BoundRegion { kind: br, .. })
- | ty::RegionKind::RePlaceholder(ty::PlaceholderRegion { name: br, .. }),
- _,
- _,
- ) => printer.region_highlight_mode.highlighting_bound_region(*br, counter),
- _ => {}
+ if let ty::Ref(region, ..) = ty.kind() {
+ match **region {
+ ty::ReLateBound(_, ty::BoundRegion { kind: br, .. })
+ | ty::RePlaceholder(ty::PlaceholderRegion { name: br, .. }) => {
+ printer.region_highlight_mode.highlighting_bound_region(br, counter)
+ }
+ _ => {}
+ }
}
let _ = ty.print(printer);
let mut s = String::new();
let mut printer = ty::print::FmtPrinter::new(self.infcx.tcx, &mut s, Namespace::TypeNS);
- let region = match ty.kind() {
- ty::Ref(region, _, _) => {
- match region {
- ty::RegionKind::ReLateBound(_, ty::BoundRegion { kind: br, .. })
- | ty::RegionKind::RePlaceholder(ty::PlaceholderRegion { name: br, .. }) => {
- printer.region_highlight_mode.highlighting_bound_region(*br, counter)
- }
- _ => {}
+ let region = if let ty::Ref(region, ..) = ty.kind() {
+ match **region {
+ ty::ReLateBound(_, ty::BoundRegion { kind: br, .. })
+ | ty::RePlaceholder(ty::PlaceholderRegion { name: br, .. }) => {
+ printer.region_highlight_mode.highlighting_bound_region(br, counter)
}
-
- region
+ _ => {}
}
- _ => bug!("ty for annotation of borrow region is not a reference"),
+ region
+ } else {
+ bug!("ty for annotation of borrow region is not a reference");
};
let _ = region.print(printer);
fn_call_span: Span,
/// The definition span of the method being called
fn_span: Span,
- kind: FnSelfUseKind<'tcx>,
+ kind: CallKind<'tcx>,
},
/// This access is caused by a `match` or `if let` pattern.
PatUse(Span),
OtherUse(Span),
}
-#[derive(Copy, Clone, PartialEq, Eq, Debug)]
-pub(super) enum FnSelfUseKind<'tcx> {
- /// A normal method call of the form `receiver.foo(a, b, c)`
- Normal {
- self_arg: Ident,
- implicit_into_iter: bool,
- /// Whether the self type of the method call has an `.as_ref()` method.
- /// Used for better diagnostics.
- is_option_or_result: bool,
- },
- /// A call to `FnOnce::call_once`, desugared from `my_closure(a, b, c)`
- FnOnceCall,
- /// A call to an operator trait, desuraged from operator syntax (e.g. `a << b`)
- Operator { self_arg: Ident },
- 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>,
- },
-}
-
impl UseSpans<'_> {
pub(super) fn args_or_use(self) -> Span {
match self {
UseSpans::ClosureUse { args_span: span, .. }
| UseSpans::PatUse(span)
| UseSpans::OtherUse(span) => span,
- UseSpans::FnSelfUse {
- fn_call_span, kind: FnSelfUseKind::DerefCoercion { .. }, ..
- } => fn_call_span,
+ UseSpans::FnSelfUse { fn_call_span, kind: CallKind::DerefCoercion { .. }, .. } => {
+ fn_call_span
+ }
UseSpans::FnSelfUse { var_span, .. } => var_span,
}
}
UseSpans::ClosureUse { path_span: span, .. }
| UseSpans::PatUse(span)
| UseSpans::OtherUse(span) => span,
- UseSpans::FnSelfUse {
- fn_call_span, kind: FnSelfUseKind::DerefCoercion { .. }, ..
- } => fn_call_span,
+ UseSpans::FnSelfUse { fn_call_span, kind: CallKind::DerefCoercion { .. }, .. } => {
+ fn_call_span
+ }
UseSpans::FnSelfUse { var_span, .. } => var_span,
}
}
UseSpans::ClosureUse { capture_kind_span: span, .. }
| UseSpans::PatUse(span)
| UseSpans::OtherUse(span) => span,
- UseSpans::FnSelfUse {
- fn_call_span, kind: FnSelfUseKind::DerefCoercion { .. }, ..
- } => fn_call_span,
+ UseSpans::FnSelfUse { fn_call_span, kind: CallKind::DerefCoercion { .. }, .. } => {
+ fn_call_span
+ }
UseSpans::FnSelfUse { var_span, .. } => var_span,
}
}
kind: TerminatorKind::Call { fn_span, from_hir_call, .. }, ..
}) = &self.body[location.block].terminator
{
- let (method_did, method_substs) = if let Some(info) =
+ let Some((method_did, method_substs)) =
rustc_const_eval::util::find_self_call(
self.infcx.tcx,
&self.body,
target_temp,
location.block,
- ) {
- info
- } else {
+ )
+ else {
return normal_ret;
};
- let tcx = self.infcx.tcx;
- let parent = tcx.parent(method_did);
- let is_fn_once = parent == tcx.lang_items().fn_once_trait();
- let is_operator = !from_hir_call
- && parent.map_or(false, |p| tcx.lang_items().group(LangItemGroup::Op).contains(&p));
- let is_deref = !from_hir_call && tcx.is_diagnostic_item(sym::deref_method, method_did);
- let fn_call_span = *fn_span;
-
- let self_arg = tcx.fn_arg_names(method_did)[0];
-
- debug!(
- "terminator = {:?} from_hir_call={:?}",
- self.body[location.block].terminator, from_hir_call
+ let kind = call_kind(
+ self.infcx.tcx,
+ self.param_env,
+ method_did,
+ method_substs,
+ *fn_span,
+ *from_hir_call,
+ Some(self.infcx.tcx.fn_arg_names(method_did)[0]),
);
- // Check for a 'special' use of 'self' -
- // an FnOnce call, an operator (e.g. `<<`), or a
- // deref coercion.
- let kind = if is_fn_once {
- Some(FnSelfUseKind::FnOnceCall)
- } else if is_operator {
- Some(FnSelfUseKind::Operator { self_arg })
- } else if is_deref {
- let deref_target =
- tcx.get_diagnostic_item(sym::deref_target).and_then(|deref_target| {
- Instance::resolve(tcx, self.param_env, deref_target, method_substs)
- .transpose()
- });
- if let Some(Ok(instance)) = deref_target {
- let deref_target_ty = instance.ty(tcx, self.param_env);
- Some(FnSelfUseKind::DerefCoercion {
- deref_target: tcx.def_span(instance.def_id()),
- deref_target_ty,
- })
- } else {
- None
- }
- } else {
- None
- };
-
- let kind = kind.unwrap_or_else(|| {
- // This isn't a 'special' use of `self`
- debug!("move_spans: method_did={:?}, fn_call_span={:?}", method_did, fn_call_span);
- let implicit_into_iter = Some(method_did) == tcx.lang_items().into_iter_fn()
- && fn_call_span.desugaring_kind() == Some(DesugaringKind::ForLoop);
- let parent_self_ty = parent
- .filter(|did| tcx.def_kind(*did) == rustc_hir::def::DefKind::Impl)
- .and_then(|did| match tcx.type_of(did).kind() {
- ty::Adt(def, ..) => Some(def.did),
- _ => None,
- });
- let is_option_or_result = parent_self_ty.map_or(false, |def_id| {
- matches!(tcx.get_diagnostic_name(def_id), Some(sym::Option | sym::Result))
- });
- FnSelfUseKind::Normal { self_arg, implicit_into_iter, is_option_or_result }
- });
-
return FnSelfUse {
var_span: stmt.source_info.span,
- fn_call_span,
+ fn_call_span: *fn_span,
fn_span: self
.infcx
.tcx