]> git.lizzy.rs Git - rust.git/blobdiff - compiler/rustc_borrowck/src/diagnostics/mod.rs
Auto merge of #107443 - cjgillot:generator-less-query, r=compiler-errors
[rust.git] / compiler / rustc_borrowck / src / diagnostics / mod.rs
index cbd590052008c14a46f3ab0b099ea517ef6f7ce9..8c579bac7e8eb471c8dc8690eb7f7c3a7c62c5d1 100644 (file)
@@ -6,7 +6,7 @@
 use rustc_hir as hir;
 use rustc_hir::def::{CtorKind, Namespace};
 use rustc_hir::GeneratorKind;
-use rustc_infer::infer::TyCtxtInferExt;
+use rustc_infer::infer::{LateBoundRegionConversionTime, TyCtxtInferExt};
 use rustc_middle::mir::tcx::PlaceTy;
 use rustc_middle::mir::{
     AggregateKind, Constant, FakeReadCause, Field, Local, LocalInfo, LocalKind, Location, Operand,
 use rustc_span::def_id::LocalDefId;
 use rustc_span::{symbol::sym, Span, Symbol, DUMMY_SP};
 use rustc_target::abi::VariantIdx;
-use rustc_trait_selection::traits::type_known_to_meet_bound_modulo_regions;
+use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt;
+use rustc_trait_selection::traits::{
+    type_known_to_meet_bound_modulo_regions, Obligation, ObligationCause,
+};
 
 use super::borrow_set::BorrowData;
 use super::MirBorrowckCtxt;
@@ -400,8 +403,7 @@ pub(super) fn note_type_does_not_implement_copy(
         move_prefix: &str,
     ) {
         let message = format!(
-            "{}move occurs because {} has type `{}`, which does not implement the `Copy` trait",
-            move_prefix, place_desc, ty,
+            "{move_prefix}move occurs because {place_desc} has type `{ty}`, which does not implement the `Copy` trait",
         );
         if let Some(span) = span {
             err.span_label(span, message);
@@ -736,11 +738,11 @@ pub(super) fn describe_for_unnamed_place(&self, tcx: TyCtxt<'_>) -> String {
             BorrowedContentSource::OverloadedDeref(ty) => ty
                 .ty_adt_def()
                 .and_then(|adt| match tcx.get_diagnostic_name(adt.did())? {
-                    name @ (sym::Rc | sym::Arc) => Some(format!("an `{}`", name)),
+                    name @ (sym::Rc | sym::Arc) => Some(format!("an `{name}`")),
                     _ => None,
                 })
-                .unwrap_or_else(|| format!("dereference of `{}`", ty)),
-            BorrowedContentSource::OverloadedIndex(ty) => format!("index of `{}`", ty),
+                .unwrap_or_else(|| format!("dereference of `{ty}`")),
+            BorrowedContentSource::OverloadedIndex(ty) => format!("index of `{ty}`"),
         }
     }
 
@@ -766,11 +768,11 @@ pub(super) fn describe_for_immutable_place(&self, tcx: TyCtxt<'_>) -> String {
             BorrowedContentSource::OverloadedDeref(ty) => ty
                 .ty_adt_def()
                 .and_then(|adt| match tcx.get_diagnostic_name(adt.did())? {
-                    name @ (sym::Rc | sym::Arc) => Some(format!("an `{}`", name)),
+                    name @ (sym::Rc | sym::Arc) => Some(format!("an `{name}`")),
                     _ => None,
                 })
-                .unwrap_or_else(|| format!("dereference of `{}`", ty)),
-            BorrowedContentSource::OverloadedIndex(ty) => format!("an index of `{}`", ty),
+                .unwrap_or_else(|| format!("dereference of `{ty}`")),
+            BorrowedContentSource::OverloadedIndex(ty) => format!("an index of `{ty}`"),
         }
     }
 
@@ -1030,7 +1032,7 @@ fn explain_captures(
         if let UseSpans::FnSelfUse { var_span, fn_call_span, fn_span, kind } = move_spans {
             let place_name = self
                 .describe_place(moved_place.as_ref())
-                .map(|n| format!("`{}`", n))
+                .map(|n| format!("`{n}`"))
                 .unwrap_or_else(|| "value".to_owned());
             match kind {
                 CallKind::FnCall { fn_trait_id, .. }
@@ -1039,8 +1041,7 @@ fn explain_captures(
                     err.span_label(
                         fn_call_span,
                         &format!(
-                            "{} {}moved due to this call{}",
-                            place_name, partially_str, loop_message
+                            "{place_name} {partially_str}moved due to this call{loop_message}",
                         ),
                     );
                     err.span_note(
@@ -1053,8 +1054,7 @@ fn explain_captures(
                     err.span_label(
                         fn_call_span,
                         &format!(
-                            "{} {}moved due to usage in operator{}",
-                            place_name, partially_str, loop_message
+                            "{place_name} {partially_str}moved due to usage in operator{loop_message}",
                         ),
                     );
                     if self.fn_self_span_reported.insert(fn_span) {
@@ -1064,20 +1064,18 @@ fn explain_captures(
                         );
                     }
                 }
-                CallKind::Normal { self_arg, desugaring, method_did } => {
+                CallKind::Normal { self_arg, desugaring, method_did, method_substs } => {
                     let self_arg = self_arg.unwrap();
+                    let tcx = self.infcx.tcx;
                     if let Some((CallDesugaringKind::ForLoopIntoIter, _)) = desugaring {
-                        let ty = moved_place.ty(self.body, self.infcx.tcx).ty;
-                        let suggest = match self.infcx.tcx.get_diagnostic_item(sym::IntoIterator) {
+                        let ty = moved_place.ty(self.body, tcx).ty;
+                        let suggest = match tcx.get_diagnostic_item(sym::IntoIterator) {
                             Some(def_id) => {
                                 let infcx = self.infcx.tcx.infer_ctxt().build();
                                 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),
-                                    ),
+                                    tcx.mk_imm_ref(tcx.lifetimes.re_erased, tcx.erase_regions(ty)),
                                     def_id,
                                     DUMMY_SP,
                                 )
@@ -1088,9 +1086,8 @@ fn explain_captures(
                             err.span_suggestion_verbose(
                                 move_span.shrink_to_lo(),
                                 &format!(
-                                    "consider iterating over a slice of the `{}`'s content to \
+                                    "consider iterating over a slice of the `{ty}`'s content to \
                                      avoid moving into the `for` loop",
-                                    ty,
                                 ),
                                 "&",
                                 Applicability::MaybeIncorrect,
@@ -1100,8 +1097,7 @@ fn explain_captures(
                         err.span_label(
                             fn_call_span,
                             &format!(
-                                "{} {}moved due to this implicit call to `.into_iter()`{}",
-                                place_name, partially_str, loop_message
+                                "{place_name} {partially_str}moved due to this implicit call to `.into_iter()`{loop_message}",
                             ),
                         );
                         // If the moved place was a `&mut` ref, then we can
@@ -1117,7 +1113,7 @@ fn explain_captures(
                                     &format!(
                                         "consider creating a fresh reborrow of {} here",
                                         self.describe_place(moved_place.as_ref())
-                                            .map(|n| format!("`{}`", n))
+                                            .map(|n| format!("`{n}`"))
                                             .unwrap_or_else(|| "the mutable reference".to_string()),
                                     ),
                                     "&mut *",
@@ -1129,12 +1125,51 @@ fn explain_captures(
                         err.span_label(
                             fn_call_span,
                             &format!(
-                                "{} {}moved due to this method call{}",
-                                place_name, partially_str, loop_message
+                                "{place_name} {partially_str}moved due to this method call{loop_message}",
                             ),
                         );
+
+                        let infcx = tcx.infer_ctxt().build();
+                        // Erase and shadow everything that could be passed to the new infcx.
+                        let ty = tcx.erase_regions(moved_place.ty(self.body, tcx).ty);
+                        let method_substs = tcx.erase_regions(method_substs);
+
+                        if let ty::Adt(def, substs) = ty.kind()
+                            && Some(def.did()) == tcx.lang_items().pin_type()
+                            && let ty::Ref(_, _, hir::Mutability::Mut) = substs.type_at(0).kind()
+                            && let self_ty = infcx.replace_bound_vars_with_fresh_vars(
+                                fn_call_span,
+                                LateBoundRegionConversionTime::FnCall,
+                                tcx.fn_sig(method_did).subst(tcx, method_substs).input(0),
+                            )
+                            && infcx.can_eq(self.param_env, ty, self_ty).is_ok()
+                        {
+                            err.span_suggestion_verbose(
+                                fn_call_span.shrink_to_lo(),
+                                "consider reborrowing the `Pin` instead of moving it",
+                                "as_mut().".to_string(),
+                                Applicability::MaybeIncorrect,
+                            );
+                        }
+                        if let Some(clone_trait) = tcx.lang_items().clone_trait()
+                            && let trait_ref = tcx.mk_trait_ref(clone_trait, [ty])
+                            && let o = Obligation::new(
+                                tcx,
+                                ObligationCause::dummy(),
+                                self.param_env,
+                                ty::Binder::dummy(trait_ref),
+                            )
+                            && infcx.predicate_must_hold_modulo_regions(&o)
+                        {
+                            err.span_suggestion_verbose(
+                                fn_call_span.shrink_to_lo(),
+                                "you can `clone` the value and consume it, but this might not be \
+                                 your desired behavior",
+                                "clone().".to_string(),
+                                Applicability::MaybeIncorrect,
+                            );
+                        }
                     }
-                    let tcx = self.infcx.tcx;
                     // Avoid pointing to the same function in multiple different
                     // error messages.
                     if span != DUMMY_SP && self.fn_self_span_reported.insert(self_arg.span) {
@@ -1169,7 +1204,7 @@ fn explain_captures(
             if move_span != span || !loop_message.is_empty() {
                 err.span_label(
                     move_span,
-                    format!("value {}moved{} here{}", partially_str, move_msg, loop_message),
+                    format!("value {partially_str}moved{move_msg} here{loop_message}"),
                 );
             }
             // If the move error occurs due to a loop, don't show
@@ -1177,7 +1212,7 @@ fn explain_captures(
             if loop_message.is_empty() {
                 move_spans.var_span_label(
                     err,
-                    format!("variable {}moved due to use{}", partially_str, move_spans.describe()),
+                    format!("variable {partially_str}moved due to use{}", move_spans.describe()),
                     "moved",
                 );
             }