about summary refs log tree commit diff
path: root/compiler/rustc_trait_selection/src
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2022-08-20 20:08:26 +0000
committerbors <bors@rust-lang.org>2022-08-20 20:08:26 +0000
commit878aef79dcdf59d19bb8482202dc55e58ceb62ff (patch)
tree8132ee767300cedc76d54a4e3e4e3bb85b891bb4 /compiler/rustc_trait_selection/src
parent48853a361a5ff0e8215301c62f259a26eed7aa72 (diff)
parentd793cd266c3163ab5ef8a109098dc409ba690e8e (diff)
downloadrust-878aef79dcdf59d19bb8482202dc55e58ceb62ff.tar.gz
rust-878aef79dcdf59d19bb8482202dc55e58ceb62ff.zip
Auto merge of #100810 - matthiaskrgr:rollup-xep778s, r=matthiaskrgr
Rollup of 9 pull requests

Successful merges:

 - #97963 (net listen backlog set to negative on Linux.)
 - #99935 (Reenable disabled early syntax gates as future-incompatibility lints)
 - #100129 (add miri-test-libstd support to libstd)
 - #100500 (Ban references to `Self` in trait object substs for projection predicates too.)
 - #100636 (Revert "Revert "Allow dynamic linking for iOS/tvOS targets."")
 - #100718 ([rustdoc] Fix item info display)
 - #100769 (Suggest adding a reference to a trait assoc item)
 - #100777 (elaborate how revisions work with FileCheck stuff in src/test/codegen)
 - #100796 (Refactor: remove unnecessary string searchings)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
Diffstat (limited to 'compiler/rustc_trait_selection/src')
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs63
1 files changed, 42 insertions, 21 deletions
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
index cae1509e640..0d279069694 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
@@ -671,7 +671,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
         trait_pred: ty::PolyTraitPredicate<'tcx>,
     ) -> bool {
         // It only make sense when suggesting dereferences for arguments
-        let ObligationCauseCode::FunctionArgumentObligation { .. } = obligation.cause.code() else {
+        let ObligationCauseCode::FunctionArgumentObligation { arg_hir_id, .. } = obligation.cause.code() else {
             return false;
         };
         let param_env = obligation.param_env;
@@ -702,19 +702,22 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
                     Some(steps).filter(|_| self.predicate_may_hold(&obligation))
                 }) {
                     if steps > 0 {
-                        if let Ok(src) = self.tcx.sess.source_map().span_to_snippet(span) {
-                            // Don't care about `&mut` because `DerefMut` is used less
-                            // often and user will not expect autoderef happens.
-                            if src.starts_with('&') && !src.starts_with("&mut ") {
-                                let derefs = "*".repeat(steps);
-                                err.span_suggestion(
-                                    span,
-                                    "consider dereferencing here",
-                                    format!("&{}{}", derefs, &src[1..]),
-                                    Applicability::MachineApplicable,
-                                );
-                                return true;
-                            }
+                        // Don't care about `&mut` because `DerefMut` is used less
+                        // often and user will not expect autoderef happens.
+                        if let Some(hir::Node::Expr(hir::Expr {
+                            kind:
+                                hir::ExprKind::AddrOf(hir::BorrowKind::Ref, hir::Mutability::Not, expr),
+                            ..
+                        })) = self.tcx.hir().find(*arg_hir_id)
+                        {
+                            let derefs = "*".repeat(steps);
+                            err.span_suggestion_verbose(
+                                expr.span.shrink_to_lo(),
+                                "consider dereferencing here",
+                                derefs,
+                                Applicability::MachineApplicable,
+                            );
+                            return true;
                         }
                     }
                 } else if real_trait_pred != trait_pred {
@@ -882,6 +885,8 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
             obligation.cause.code()
         {
             &parent_code
+        } else if let ObligationCauseCode::ItemObligation(_) = obligation.cause.code() {
+            obligation.cause.code()
         } else if let ExpnKind::Desugaring(DesugaringKind::ForLoop) =
             span.ctxt().outer_expn_data().kind
         {
@@ -930,10 +935,25 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
                         self.mk_trait_obligation_with_new_self_ty(param_env, trait_pred_and_new_ty);
                     self.predicate_must_hold_modulo_regions(&obligation)
                 };
-                let imm_result = mk_result(trait_pred_and_imm_ref);
-                let mut_result = mk_result(trait_pred_and_mut_ref);
+                let imm_ref_self_ty_satisfies_pred = mk_result(trait_pred_and_imm_ref);
+                let mut_ref_self_ty_satisfies_pred = mk_result(trait_pred_and_mut_ref);
+
+                let (ref_inner_ty_satisfies_pred, ref_inner_ty_mut) =
+                if let ObligationCauseCode::ItemObligation(_) = obligation.cause.code()
+                    && let ty::Ref(_, ty, mutability) = old_pred.self_ty().skip_binder().kind()
+                {
+                    (
+                        mk_result(old_pred.map_bound(|trait_pred| (trait_pred, *ty))),
+                        matches!(mutability, hir::Mutability::Mut),
+                    )
+                } else {
+                    (false, false)
+                };
 
-                if imm_result || mut_result {
+                if imm_ref_self_ty_satisfies_pred
+                    || mut_ref_self_ty_satisfies_pred
+                    || ref_inner_ty_satisfies_pred
+                {
                     if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) {
                         // We have a very specific type of error, where just borrowing this argument
                         // might solve the problem. In cases like this, the important part is the
@@ -973,7 +993,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
                             // }
                             // ```
 
-                            if imm_result && mut_result {
+                            if imm_ref_self_ty_satisfies_pred && mut_ref_self_ty_satisfies_pred {
                                 err.span_suggestions(
                                     span.shrink_to_lo(),
                                     "consider borrowing here",
@@ -981,13 +1001,14 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
                                     Applicability::MaybeIncorrect,
                                 );
                             } else {
+                                let is_mut = mut_ref_self_ty_satisfies_pred || ref_inner_ty_mut;
                                 err.span_suggestion_verbose(
                                     span.shrink_to_lo(),
                                     &format!(
                                         "consider{} borrowing here",
-                                        if mut_result { " mutably" } else { "" }
+                                        if is_mut { " mutably" } else { "" }
                                     ),
-                                    format!("&{}", if mut_result { "mut " } else { "" }),
+                                    format!("&{}", if is_mut { "mut " } else { "" }),
                                     Applicability::MaybeIncorrect,
                                 );
                             }
@@ -1001,7 +1022,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
         if let ObligationCauseCode::ImplDerivedObligation(cause) = &*code {
             try_borrowing(cause.derived.parent_trait_pred, &[])
         } else if let ObligationCauseCode::BindingObligation(_, _)
-        | ObligationCauseCode::ItemObligation(_) = code
+        | ObligationCauseCode::ItemObligation(..) = code
         {
             try_borrowing(poly_trait_pred, &never_suggest_borrow)
         } else {