about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs142
1 files changed, 76 insertions, 66 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 8e393550509..f9a63841a70 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
@@ -1758,73 +1758,8 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
 
         self.note_conflicting_closure_bounds(cause, &mut err);
 
-        let found_args = match found.kind() {
-            ty::FnPtr(f) => f.inputs().skip_binder().iter(),
-            kind => {
-                span_bug!(span, "found was converted to a FnPtr above but is now {:?}", kind)
-            }
-        };
-        let expected_args = match expected.kind() {
-            ty::FnPtr(f) => f.inputs().skip_binder().iter(),
-            kind => {
-                span_bug!(span, "expected was converted to a FnPtr above but is now {:?}", kind)
-            }
-        };
-
         if let Some(found_node) = found_node {
-            let fn_decl = match found_node {
-                Node::Expr(expr) => match &expr.kind {
-                    hir::ExprKind::Closure(hir::Closure { fn_decl, .. }) => fn_decl,
-                    kind => {
-                        span_bug!(found_span, "expression must be a closure but is {:?}", kind)
-                    }
-                },
-                Node::Item(item) => match &item.kind {
-                    hir::ItemKind::Fn(signature, _generics, _body) => signature.decl,
-                    kind => {
-                        span_bug!(found_span, "item must be a function but is {:?}", kind)
-                    }
-                },
-                node => {
-                    span_bug!(found_span, "node must be a expr or item but is {:?}", node)
-                }
-            };
-
-            let arg_spans = fn_decl.inputs.iter().map(|ty| ty.span);
-
-            fn get_deref_type_and_refs(mut ty: Ty<'_>) -> (Ty<'_>, usize) {
-                let mut refs = 0;
-
-                while let ty::Ref(_, new_ty, _) = ty.kind() {
-                    ty = *new_ty;
-                    refs += 1;
-                }
-
-                (ty, refs)
-            }
-
-            for ((found_arg, expected_arg), arg_span) in
-                found_args.zip(expected_args).zip(arg_spans)
-            {
-                let (found_ty, found_refs) = get_deref_type_and_refs(*found_arg);
-                let (expected_ty, expected_refs) = get_deref_type_and_refs(*expected_arg);
-
-                if found_ty == expected_ty {
-                    let hint = if found_refs < expected_refs {
-                        "consider borrowing here:"
-                    } else if found_refs == expected_refs {
-                        continue;
-                    } else {
-                        "consider removing the borrow:"
-                    };
-                    err.span_suggestion_verbose(
-                        arg_span,
-                        hint,
-                        expected_arg.to_string(),
-                        Applicability::MaybeIncorrect,
-                    );
-                }
-            }
+            hint_missing_borrow(span, found_span, found, expected, found_node, &mut err);
         }
 
         err
@@ -3455,6 +3390,81 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
     }
 }
 
+/// 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<'_>,
+    err: &mut Diagnostic,
+) {
+    let found_args = match found.kind() {
+        ty::FnPtr(f) => f.inputs().skip_binder().iter(),
+        kind => {
+            span_bug!(span, "found was converted to a FnPtr above but is now {:?}", kind)
+        }
+    };
+    let expected_args = match expected.kind() {
+        ty::FnPtr(f) => f.inputs().skip_binder().iter(),
+        kind => {
+            span_bug!(span, "expected was converted to a FnPtr above but is now {:?}", kind)
+        }
+    };
+
+    let fn_decl = match found_node {
+        Node::Expr(expr) => match &expr.kind {
+            hir::ExprKind::Closure(hir::Closure { fn_decl, .. }) => fn_decl,
+            kind => {
+                span_bug!(found_span, "expression must be a closure but is {:?}", kind)
+            }
+        },
+        Node::Item(item) => match &item.kind {
+            hir::ItemKind::Fn(signature, _generics, _body) => signature.decl,
+            kind => {
+                span_bug!(found_span, "item must be a function but is {:?}", kind)
+            }
+        },
+        node => {
+            span_bug!(found_span, "node must be a expr or item but is {:?}", node)
+        }
+    };
+
+    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) {
+        let mut refs = 0;
+
+        while let ty::Ref(_, new_ty, _) = ty.kind() {
+            ty = *new_ty;
+            refs += 1;
+        }
+
+        (ty, refs)
+    }
+
+    for ((found_arg, expected_arg), arg_span) in found_args.zip(expected_args).zip(arg_spans) {
+        let (found_ty, found_refs) = get_deref_type_and_refs(*found_arg);
+        let (expected_ty, expected_refs) = get_deref_type_and_refs(*expected_arg);
+
+        if found_ty == expected_ty {
+            let hint = if found_refs < expected_refs {
+                "consider borrowing here:"
+            } else if found_refs == expected_refs {
+                continue;
+            } else {
+                "consider removing the borrow:"
+            };
+            err.span_suggestion_verbose(
+                arg_span,
+                hint,
+                expected_arg.to_string(),
+                Applicability::MaybeIncorrect,
+            );
+        }
+    }
+}
+
 /// Collect all the returned expressions within the input expression.
 /// Used to point at the return spans when we want to suggest some change to them.
 #[derive(Default)]