]> git.proxmox.com Git - rustc.git/blobdiff - compiler/rustc_borrowck/src/diagnostics/mod.rs
New upstream version 1.60.0+dfsg1
[rustc.git] / compiler / rustc_borrowck / src / diagnostics / mod.rs
index e2eb125981f138b718742eaab4a5ca1bd6eab131..73b0d3982850469470f8dd6eda073a321034adb8 100644 (file)
@@ -1,10 +1,10 @@
 //! 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,
@@ -13,7 +13,7 @@ use rustc_middle::mir::{
 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;
@@ -37,7 +37,7 @@ crate use mutability_errors::AccessKind;
 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);
 
@@ -331,7 +331,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
         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 => {
@@ -339,10 +339,10 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                 }
                 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 { .. }
@@ -362,7 +362,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
     ) -> 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, _) => {
@@ -372,14 +372,14 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                     } 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,
@@ -497,14 +497,14 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
         // 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);
@@ -517,19 +517,17 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
         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);
@@ -563,7 +561,7 @@ pub(super) enum UseSpans<'tcx> {
         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),
@@ -571,38 +569,15 @@ pub(super) enum UseSpans<'tcx> {
     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,
         }
     }
@@ -613,9 +588,9 @@ impl UseSpans<'_> {
             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,
         }
     }
@@ -626,9 +601,9 @@ impl UseSpans<'_> {
             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,
         }
     }
@@ -892,79 +867,30 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
             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