]> git.lizzy.rs Git - rust.git/blobdiff - compiler/rustc_borrowck/src/diagnostics/mod.rs
Rollup merge of #107103 - compiler-errors:new-solver-evaluate_obligation, r=lcnr
[rust.git] / compiler / rustc_borrowck / src / diagnostics / mod.rs
index 762188b73b38e268fa60d5683e622bb423b421e3..1011794d7b3b2995671c2946070a4f59df385fcb 100644 (file)
@@ -6,8 +6,7 @@
 use rustc_hir as hir;
 use rustc_hir::def::{CtorKind, Namespace};
 use rustc_hir::GeneratorKind;
-use rustc_hir_analysis::hir_ty_to_ty;
-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;
@@ -401,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);
@@ -737,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}`"),
         }
     }
 
@@ -767,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}`"),
         }
     }
 
@@ -1031,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, .. }
@@ -1040,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(
@@ -1054,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) {
@@ -1065,7 +1064,7 @@ 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 {
@@ -1087,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,
@@ -1099,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
@@ -1116,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 *",
@@ -1128,17 +1125,20 @@ 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 ty = tcx.erase_regions(moved_place.ty(self.body, self.infcx.tcx).ty);
+                        let infcx = tcx.infer_ctxt().build();
+                        let ty = tcx.erase_regions(moved_place.ty(self.body, tcx).ty);
                         if let ty::Adt(def, substs) = ty.kind()
-                            && Some(def.did()) == self.infcx.tcx.lang_items().pin_type()
+                            && Some(def.did()) == tcx.lang_items().pin_type()
                             && let ty::Ref(_, _, hir::Mutability::Mut) = substs.type_at(0).kind()
-                            // FIXME: this is a hack because we can't call `can_eq`
-                            && ty.to_string() ==    
-                                tcx.fn_sig(method_did).input(0).skip_binder().to_string()
+                            && 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(),
@@ -1147,32 +1147,23 @@ fn explain_captures(
                                 Applicability::MaybeIncorrect,
                             );
                         }
-                        if let Some(clone_trait) = tcx.lang_items().clone_trait() {
-                            // We can't use `predicate_may_hold` or `can_eq` without ICEs in
-                            // borrowck because of the inference context, so we do a poor-man's
-                            // version here.
-                            for impl_def_id in tcx.all_impls(clone_trait) {
-                                if let Some(def_id) = impl_def_id.as_local()
-                                    && let hir_id = tcx.hir().local_def_id_to_hir_id(def_id)
-                                    && let hir::Node::Item(hir::Item {
-                                        kind: hir::ItemKind::Impl(hir::Impl {
-                                            self_ty,
-                                            ..
-                                        }),
-                                        ..
-                                    }) = tcx.hir().get(hir_id)
-                                {
-                                    if ty == hir_ty_to_ty(tcx, self_ty) {
-                                        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,
-                                        );
-                                    }
-                                }
-                            }
+                        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,
+                            );
                         }
                     }
                     // Avoid pointing to the same function in multiple different
@@ -1209,7 +1200,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
@@ -1217,7 +1208,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",
                 );
             }