]> git.lizzy.rs Git - rust.git/blobdiff - src/librustc_mir/borrow_check/diagnostics/mod.rs
Provide suggestions for some moved value errors
[rust.git] / src / librustc_mir / borrow_check / diagnostics / mod.rs
index 04f48cd65823054613daa1804218756a462b30bc..388076a9d60afb77ba09af01bf74a40f8b0c6cd5 100644 (file)
 };
 use rustc_middle::ty::print::Print;
 use rustc_middle::ty::{self, DefIdTree, Ty, TyCtxt};
-use rustc_span::{
-    hygiene::{DesugaringKind, ForLoopLoc},
-    symbol::sym,
-    Span,
-};
+use rustc_span::{symbol::sym, Span};
 use rustc_target::abi::VariantIdx;
 
 use super::borrow_set::BorrowData;
@@ -37,7 +33,6 @@
 crate use outlives_suggestion::OutlivesSuggestionBuilder;
 crate use region_errors::{ErrorConstraintInfo, RegionErrorKind, RegionErrors};
 crate use region_name::{RegionName, RegionNameSource};
-use rustc_span::symbol::Ident;
 
 pub(super) struct IncludingDowncast(pub(super) bool);
 
@@ -534,49 +529,30 @@ pub(super) fn get_region_name_for_ty(&self, ty: Ty<'tcx>, counter: usize) -> Str
     }
 }
 
-/// The span(s) associated to a use of a place.
+// The span(s) associated to a use of a place.
 #[derive(Copy, Clone, PartialEq, Eq, Debug)]
 pub(super) enum UseSpans {
-    /// The access is caused by capturing a variable for a closure.
+    // The access is caused by capturing a variable for a closure.
     ClosureUse {
-        /// This is true if the captured variable was from a generator.
+        // This is true if the captured variable was from a generator.
         generator_kind: Option<GeneratorKind>,
-        /// The span of the args of the closure, including the `move` keyword if
-        /// it's present.
+        // The span of the args of the closure, including the `move` keyword if
+        // it's present.
         args_span: Span,
-        /// The span of the first use of the captured variable inside the closure.
-        var_span: Span,
-    },
-    /// The access is caused by using a variable as the receiver of a method
-    /// that takes 'self'
-    FnSelfUse {
-        /// The span of the variable being moved
+        // The span of the first use of the captured variable inside the closure.
         var_span: Span,
-        /// The span of the method call on the variable
-        fn_call_span: Span,
-        /// The definition span of the method being called
-        fn_span: Span,
-        kind: FnSelfUseKind,
     },
-    // This access has a single span associated to it: common case.
+    /// This access is caused by a `match` or `if let` pattern.
+    PatUse(Span),
+    /// This access has a single span associated to it: common case.
     OtherUse(Span),
 }
 
-#[derive(Copy, Clone, PartialEq, Eq, Debug)]
-pub(super) enum FnSelfUseKind {
-    /// A normal method call of the form `receiver.foo(a, b, c)`
-    Normal { self_arg: Ident, implicit_into_iter: 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 },
-}
-
 impl UseSpans {
     pub(super) fn args_or_use(self) -> Span {
         match self {
             UseSpans::ClosureUse { args_span: span, .. }
-            | UseSpans::FnSelfUse { var_span: span, .. }
+            | UseSpans::PatUse(span)
             | UseSpans::OtherUse(span) => span,
         }
     }
@@ -584,7 +560,7 @@ pub(super) fn args_or_use(self) -> Span {
     pub(super) fn var_or_use(self) -> Span {
         match self {
             UseSpans::ClosureUse { var_span: span, .. }
-            | UseSpans::FnSelfUse { var_span: span, .. }
+            | UseSpans::PatUse(span)
             | UseSpans::OtherUse(span) => span,
         }
     }
@@ -654,8 +630,7 @@ pub(super) fn or_else<F>(self, if_other: F) -> Self
     {
         match self {
             closure @ UseSpans::ClosureUse { .. } => closure,
-            fn_self @ UseSpans::FnSelfUse { .. } => fn_self,
-            UseSpans::OtherUse(_) => if_other(),
+            UseSpans::PatUse(_) | UseSpans::OtherUse(_) => if_other(),
         }
     }
 }
@@ -758,100 +733,25 @@ pub(super) fn move_spans(
 
         debug!("move_spans: moved_place={:?} location={:?} stmt={:?}", moved_place, location, stmt);
         if let StatementKind::Assign(box (_, Rvalue::Aggregate(ref kind, ref places))) = stmt.kind {
-            match kind {
+            let def_id = match kind {
                 box AggregateKind::Closure(def_id, _)
-                | box AggregateKind::Generator(def_id, _, _) => {
-                    debug!("move_spans: def_id={:?} places={:?}", def_id, places);
-                    if let Some((args_span, generator_kind, var_span)) =
-                        self.closure_span(*def_id, moved_place, places)
-                    {
-                        return ClosureUse { generator_kind, args_span, var_span };
-                    }
-                }
-                _ => {}
-            }
-        }
-
-        let normal_ret = OtherUse(stmt.source_info.span);
-
-        // We are trying to find MIR of the form:
-        // ```
-        // _temp = _moved_val;
-        // ...
-        // FnSelfCall(_temp, ...)
-        // ```
-        //
-        // where `_moved_val` is the place we generated the move error for,
-        // `_temp` is some other local, and `FnSelfCall` is a function
-        // that has a `self` parameter.
-
-        let target_temp = match stmt.kind {
-            StatementKind::Assign(box (temp, _)) if temp.as_local().is_some() => {
-                temp.as_local().unwrap()
-            }
-            _ => return normal_ret,
-        };
-
-        debug!("move_spans: target_temp = {:?}", target_temp);
+                | box AggregateKind::Generator(def_id, _, _) => def_id,
+                _ => return OtherUse(stmt.source_info.span),
+            };
 
-        if let Some(Terminator { kind: TerminatorKind::Call { func, args, fn_span, .. }, .. }) =
-            &self.body[location.block].terminator
-        {
-            let mut method_did = None;
-            if let Operand::Constant(box Constant { literal: ty::Const { ty, .. }, .. }) = func {
-                if let ty::FnDef(def_id, _) = ty.kind {
-                    debug!("move_spans: fn = {:?}", def_id);
-                    if let Some(ty::AssocItem { fn_has_self_parameter, .. }) =
-                        self.infcx.tcx.opt_associated_item(def_id)
-                    {
-                        if *fn_has_self_parameter {
-                            method_did = Some(def_id);
-                        }
-                    }
-                }
+            debug!("move_spans: def_id={:?} places={:?}", def_id, places);
+            if let Some((args_span, generator_kind, var_span)) =
+                self.closure_span(*def_id, moved_place, places)
+            {
+                return ClosureUse { generator_kind, args_span, var_span };
             }
+        }
 
-            let tcx = self.infcx.tcx;
-            let method_did = if let Some(did) = method_did { did } else { return normal_ret };
-
-            if let [Operand::Move(self_place), ..] = **args {
-                if self_place.as_local() == Some(target_temp) {
-                    let is_fn_once = tcx.parent(method_did) == tcx.lang_items().fn_once_trait();
-                    let fn_call_span = *fn_span;
-
-                    let self_arg = tcx.fn_arg_names(method_did)[0];
-
-                    let kind = if is_fn_once {
-                        FnSelfUseKind::FnOnceCall
-                    } else if fn_call_span.is_desugaring(DesugaringKind::Operator) {
-                        FnSelfUseKind::Operator { self_arg }
-                    } else {
-                        debug!(
-                            "move_spans: method_did={:?}, fn_call_span={:?}",
-                            method_did, fn_call_span
-                        );
-                        let implicit_into_iter = matches!(
-                            fn_call_span.desugaring_kind(),
-                            Some(DesugaringKind::ForLoop(ForLoopLoc::IntoIter))
-                        );
-                        FnSelfUseKind::Normal { self_arg, implicit_into_iter }
-                    };
-
-                    return FnSelfUse {
-                        var_span: stmt.source_info.span,
-                        fn_call_span,
-                        fn_span: self
-                            .infcx
-                            .tcx
-                            .sess
-                            .source_map()
-                            .guess_head_span(self.infcx.tcx.def_span(method_did)),
-                        kind,
-                    };
-                }
-            }
+        if moved_place.projection.iter().any(|p| matches!(p, ProjectionElem::Downcast(..))) {
+            PatUse(stmt.source_info.span)
+        } else {
+            OtherUse(stmt.source_info.span)
         }
-        return normal_ret;
     }
 
     /// Finds the span of arguments of a closure (within `maybe_closure_span`)