]> git.proxmox.com Git - rustc.git/blobdiff - compiler/rustc_mir/src/borrow_check/diagnostics/move_errors.rs
New upstream version 1.56.0~beta.4+dfsg1
[rustc.git] / compiler / rustc_mir / src / borrow_check / diagnostics / move_errors.rs
index 3f87d9c7ac94811ebb95ba53e97bed6b7e8bfcea..66e06325fa982df6d564fa048a2284c2a10343c3 100644 (file)
@@ -1,8 +1,10 @@
 use rustc_errors::{Applicability, DiagnosticBuilder};
+use rustc_infer::infer::TyCtxtInferExt;
 use rustc_middle::mir::*;
 use rustc_middle::ty;
 use rustc_span::source_map::DesugaringKind;
-use rustc_span::{sym, Span};
+use rustc_span::{sym, Span, DUMMY_SP};
+use rustc_trait_selection::traits::type_known_to_meet_bound_modulo_regions;
 
 use crate::borrow_check::diagnostics::UseSpans;
 use crate::borrow_check::prefixes::PrefixSet;
@@ -384,36 +386,48 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
                 }
             }
         };
-        if let Ok(snippet) = self.infcx.tcx.sess.source_map().span_to_snippet(span) {
-            let def_id = match *move_place.ty(self.body, self.infcx.tcx).ty.kind() {
-                ty::Adt(self_def, _) => self_def.did,
-                ty::Foreign(def_id)
-                | ty::FnDef(def_id, _)
-                | ty::Closure(def_id, _)
-                | ty::Generator(def_id, ..)
-                | ty::Opaque(def_id, _) => def_id,
-                _ => return err,
+        let ty = move_place.ty(self.body, self.infcx.tcx).ty;
+        let def_id = match *ty.kind() {
+            ty::Adt(self_def, _) => self_def.did,
+            ty::Foreign(def_id)
+            | ty::FnDef(def_id, _)
+            | ty::Closure(def_id, _)
+            | ty::Generator(def_id, ..)
+            | ty::Opaque(def_id, _) => def_id,
+            _ => return err,
+        };
+        let is_option = self.infcx.tcx.is_diagnostic_item(sym::option_type, def_id);
+        let is_result = self.infcx.tcx.is_diagnostic_item(sym::result_type, def_id);
+        if (is_option || is_result) && use_spans.map_or(true, |v| !v.for_closure()) {
+            err.span_suggestion_verbose(
+                span.shrink_to_hi(),
+                &format!(
+                    "consider borrowing the `{}`'s content",
+                    if is_option { "Option" } else { "Result" }
+                ),
+                ".as_ref()".to_string(),
+                Applicability::MaybeIncorrect,
+            );
+        } else if matches!(span.desugaring_kind(), Some(DesugaringKind::ForLoop(_))) {
+            let suggest = match self.infcx.tcx.get_diagnostic_item(sym::IntoIterator) {
+                Some(def_id) => self.infcx.tcx.infer_ctxt().enter(|infcx| {
+                    type_known_to_meet_bound_modulo_regions(
+                        &infcx,
+                        self.param_env,
+                        infcx
+                            .tcx
+                            .mk_imm_ref(infcx.tcx.lifetimes.re_erased, infcx.tcx.erase_regions(ty)),
+                        def_id,
+                        DUMMY_SP,
+                    )
+                }),
+                _ => false,
             };
-            let is_option = self.infcx.tcx.is_diagnostic_item(sym::option_type, def_id);
-            let is_result = self.infcx.tcx.is_diagnostic_item(sym::result_type, def_id);
-            if (is_option || is_result) && use_spans.map_or(true, |v| !v.for_closure()) {
-                err.span_suggestion(
-                    span,
-                    &format!(
-                        "consider borrowing the `{}`'s content",
-                        if is_option { "Option" } else { "Result" }
-                    ),
-                    format!("{}.as_ref()", snippet),
-                    Applicability::MaybeIncorrect,
-                );
-            } else if matches!(span.desugaring_kind(), Some(DesugaringKind::ForLoop(_)))
-                && self.infcx.tcx.is_diagnostic_item(sym::vec_type, def_id)
-            {
-                // FIXME: suggest for anything that implements `IntoIterator`.
-                err.span_suggestion(
-                    span,
-                    "consider iterating over a slice of the `Vec<_>`'s content",
-                    format!("&{}", snippet),
+            if suggest {
+                err.span_suggestion_verbose(
+                    span.shrink_to_lo(),
+                    &format!("consider iterating over a slice of the `{}`'s content", ty),
+                    "&".to_string(),
                     Applicability::MaybeIncorrect,
                 );
             }