]> git.lizzy.rs Git - rust.git/blobdiff - compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
Merge from rustc
[rust.git] / compiler / rustc_trait_selection / src / traits / error_reporting / suggestions.rs
index d47a5ea3e3706fa68ddcda5e27f80186ab6ca550..9656bfbf4ecc161fb6e6dbd31acb750bb8daee4e 100644 (file)
@@ -335,7 +335,7 @@ fn suggest_dereferencing_index(
         err: &mut Diagnostic,
         trait_pred: ty::PolyTraitPredicate<'tcx>,
     );
-    fn function_argument_obligation(
+    fn note_function_argument_obligation(
         &self,
         arg_hir_id: HirId,
         err: &mut Diagnostic,
@@ -1789,7 +1789,7 @@ pub(crate) fn build_fn_sig_ty<'tcx>(
         self.note_conflicting_closure_bounds(cause, &mut err);
 
         if let Some(found_node) = found_node {
-            hint_missing_borrow(span, found_span, found, expected, found_node, &mut err);
+            hint_missing_borrow(span, found, expected, found_node, &mut err);
         }
 
         err
@@ -2344,28 +2344,33 @@ fn note_obligation_cause_for_async_await(
                 }
             }
             GeneratorInteriorOrUpvar::Upvar(upvar_span) => {
-                // `Some(ref_ty)` if `target_ty` is `&T` and `T` fails to impl `Sync`
-                let refers_to_non_sync = match target_ty.kind() {
-                    ty::Ref(_, ref_ty, _) => match self.evaluate_obligation(&obligation) {
-                        Ok(eval) if !eval.may_apply() => Some(ref_ty),
+                // `Some((ref_ty, is_mut))` if `target_ty` is `&T` or `&mut T` and fails to impl `Send`
+                let non_send = match target_ty.kind() {
+                    ty::Ref(_, ref_ty, mutability) => match self.evaluate_obligation(&obligation) {
+                        Ok(eval) if !eval.may_apply() => Some((ref_ty, mutability.is_mut())),
                         _ => None,
                     },
                     _ => None,
                 };
 
-                let (span_label, span_note) = match refers_to_non_sync {
-                    // if `target_ty` is `&T` and `T` fails to impl `Sync`,
-                    // include suggestions to make `T: Sync` so that `&T: Send`
-                    Some(ref_ty) => (
-                        format!(
-                            "has type `{}` which {}, because `{}` is not `Sync`",
-                            target_ty, trait_explanation, ref_ty
-                        ),
-                        format!(
-                            "captured value {} because `&` references cannot be sent unless their referent is `Sync`",
-                            trait_explanation
-                        ),
-                    ),
+                let (span_label, span_note) = match non_send {
+                    // if `target_ty` is `&T` or `&mut T` and fails to impl `Send`,
+                    // include suggestions to make `T: Sync` so that `&T: Send`,
+                    // or to make `T: Send` so that `&mut T: Send`
+                    Some((ref_ty, is_mut)) => {
+                        let ref_ty_trait = if is_mut { "Send" } else { "Sync" };
+                        let ref_kind = if is_mut { "&mut" } else { "&" };
+                        (
+                            format!(
+                                "has type `{}` which {}, because `{}` is not `{}`",
+                                target_ty, trait_explanation, ref_ty, ref_ty_trait
+                            ),
+                            format!(
+                                "captured value {} because `{}` references cannot be sent unless their referent is `{}`",
+                                trait_explanation, ref_kind, ref_ty_trait
+                            ),
+                        )
+                    }
                     None => (
                         format!("has type `{}` which {}", target_ty, trait_explanation),
                         format!("captured value {}", trait_explanation),
@@ -2740,7 +2745,7 @@ fn note_obligation_cause_code<T>(
                             }
                             ty::Closure(def_id, _) => err.span_note(
                                 self.tcx.def_span(def_id),
-                                &format!("required because it's used within this closure"),
+                                "required because it's used within this closure",
                             ),
                             _ => err.note(&msg),
                         };
@@ -2904,7 +2909,7 @@ fn note_obligation_cause_code<T>(
                 ref parent_code,
                 ..
             } => {
-                self.function_argument_obligation(
+                self.note_function_argument_obligation(
                     arg_hir_id,
                     err,
                     parent_code,
@@ -3136,23 +3141,20 @@ fn suggest_dereferencing_index(
             );
         }
     }
-    fn function_argument_obligation(
+    fn note_function_argument_obligation(
         &self,
         arg_hir_id: HirId,
         err: &mut Diagnostic,
         parent_code: &ObligationCauseCode<'tcx>,
         param_env: ty::ParamEnv<'tcx>,
-        predicate: ty::Predicate<'tcx>,
+        failed_pred: ty::Predicate<'tcx>,
         call_hir_id: HirId,
     ) {
         let tcx = self.tcx;
         let hir = tcx.hir();
-        if let Some(Node::Expr(expr)) = hir.find(arg_hir_id) {
-            let parent_id = hir.get_parent_item(arg_hir_id);
-            let typeck_results: &TypeckResults<'tcx> = match &self.typeck_results {
-                Some(t) if t.hir_owner == parent_id => t,
-                _ => self.tcx.typeck(parent_id.def_id),
-            };
+        if let Some(Node::Expr(expr)) = hir.find(arg_hir_id)
+            && let Some(typeck_results) = &self.typeck_results
+        {
             if let hir::Expr { kind: hir::ExprKind::Block(..), .. } = expr {
                 let expr = expr.peel_blocks();
                 let ty = typeck_results.expr_ty_adjusted_opt(expr).unwrap_or(tcx.ty_error());
@@ -3177,37 +3179,29 @@ fn function_argument_obligation(
             let mut type_diffs = vec![];
 
             if let ObligationCauseCode::ExprBindingObligation(def_id, _, _, idx) = parent_code.deref()
-                && let predicates = self.tcx.predicates_of(def_id).instantiate_identity(self.tcx)
-                && let Some(pred) = predicates.predicates.get(*idx)
+                && let Some(node_substs) = typeck_results.node_substs_opt(call_hir_id)
+                && let where_clauses = self.tcx.predicates_of(def_id).instantiate(self.tcx, node_substs)
+                && let Some(where_pred) = where_clauses.predicates.get(*idx)
             {
-                if let Ok(trait_pred) = pred.kind().try_map_bound(|pred| match pred {
-                    ty::PredicateKind::Clause(ty::Clause::Trait(trait_pred)) => Ok(trait_pred),
-                    _ => Err(()),
-                })
-                    && let Ok(trait_predicate) = predicate.kind().try_map_bound(|pred| match pred {
-                        ty::PredicateKind::Clause(ty::Clause::Trait(trait_pred)) => Ok(trait_pred),
-                        _ => Err(()),
-                    })
+                if let Some(where_pred) = where_pred.to_opt_poly_trait_pred()
+                    && let Some(failed_pred) = failed_pred.to_opt_poly_trait_pred()
                 {
                     let mut c = CollectAllMismatches {
                         infcx: self.infcx,
                         param_env,
                         errors: vec![],
                     };
-                    if let Ok(_) = c.relate(trait_pred, trait_predicate) {
+                    if let Ok(_) = c.relate(where_pred, failed_pred) {
                         type_diffs = c.errors;
                     }
-                } else if let ty::PredicateKind::Clause(
-                    ty::Clause::Projection(proj)
-                ) = pred.kind().skip_binder()
-                    && let ty::PredicateKind::Clause(
-                        ty::Clause::Projection(projection)
-                    ) = predicate.kind().skip_binder()
+                } else if let Some(where_pred) = where_pred.to_opt_poly_projection_pred()
+                    && let Some(failed_pred) = failed_pred.to_opt_poly_projection_pred()
+                    && let Some(found) = failed_pred.skip_binder().term.ty()
                 {
                     type_diffs = vec![
                         Sorts(ty::error::ExpectedFound {
-                            expected: self.tcx.mk_ty(ty::Alias(ty::Projection, proj.projection_ty)),
-                            found: projection.term.ty().unwrap(),
+                            expected: self.tcx.mk_ty(ty::Alias(ty::Projection, where_pred.skip_binder().projection_ty)),
+                            found,
                         }),
                     ];
                 }
@@ -3222,9 +3216,9 @@ fn function_argument_obligation(
                 // If the expression we're calling on is a binding, we want to point at the
                 // `let` when talking about the type. Otherwise we'll point at every part
                 // of the method chain with the type.
-                self.point_at_chain(binding_expr, typeck_results, type_diffs, param_env, err);
+                self.point_at_chain(binding_expr, &typeck_results, type_diffs, param_env, err);
             } else {
-                self.point_at_chain(expr, typeck_results, type_diffs, param_env, err);
+                self.point_at_chain(expr, &typeck_results, type_diffs, param_env, err);
             }
         }
         let call_node = hir.find(call_hir_id);
@@ -3386,7 +3380,7 @@ fn point_at_chain(
             }
             err.span_note(
                 multi_span,
-                format!("the method call chain might not have had the expected associated types"),
+                "the method call chain might not have had the expected associated types",
             );
         }
     }
@@ -3455,7 +3449,6 @@ fn probe_assoc_types_at_expr(
 /// Add a hint to add a missing borrow or remove an unnecessary one.
 fn hint_missing_borrow<'tcx>(
     span: Span,
-    found_span: Span,
     found: Ty<'tcx>,
     expected: Ty<'tcx>,
     found_node: Node<'_>,
@@ -3474,13 +3467,12 @@ fn hint_missing_borrow<'tcx>(
         }
     };
 
-    let fn_decl = found_node
-        .fn_decl()
-        .unwrap_or_else(|| span_bug!(found_span, "found node must be a function"));
+    // This could be a variant constructor, for example.
+    let Some(fn_decl) = found_node.fn_decl() else { return; };
 
     let arg_spans = fn_decl.inputs.iter().map(|ty| ty.span);
 
-    fn get_deref_type_and_refs<'tcx>(mut ty: Ty<'tcx>) -> (Ty<'tcx>, usize) {
+    fn get_deref_type_and_refs(mut ty: Ty<'_>) -> (Ty<'_>, usize) {
         let mut refs = 0;
 
         while let ty::Ref(_, new_ty, _) = ty.kind() {