@@ -1758,73 +1758,8 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
17581758
17591759 self . note_conflicting_closure_bounds ( cause, & mut err) ;
17601760
1761- let found_args = match found. kind ( ) {
1762- ty:: FnPtr ( f) => f. inputs ( ) . skip_binder ( ) . iter ( ) ,
1763- kind => {
1764- span_bug ! ( span, "found was converted to a FnPtr above but is now {:?}" , kind)
1765- }
1766- } ;
1767- let expected_args = match expected. kind ( ) {
1768- ty:: FnPtr ( f) => f. inputs ( ) . skip_binder ( ) . iter ( ) ,
1769- kind => {
1770- span_bug ! ( span, "expected was converted to a FnPtr above but is now {:?}" , kind)
1771- }
1772- } ;
1773-
17741761 if let Some ( found_node) = found_node {
1775- let fn_decl = match found_node {
1776- Node :: Expr ( expr) => match & expr. kind {
1777- hir:: ExprKind :: Closure ( hir:: Closure { fn_decl, .. } ) => fn_decl,
1778- kind => {
1779- span_bug ! ( found_span, "expression must be a closure but is {:?}" , kind)
1780- }
1781- } ,
1782- Node :: Item ( item) => match & item. kind {
1783- hir:: ItemKind :: Fn ( signature, _generics, _body) => signature. decl ,
1784- kind => {
1785- span_bug ! ( found_span, "item must be a function but is {:?}" , kind)
1786- }
1787- } ,
1788- node => {
1789- span_bug ! ( found_span, "node must be a expr or item but is {:?}" , node)
1790- }
1791- } ;
1792-
1793- let arg_spans = fn_decl. inputs . iter ( ) . map ( |ty| ty. span ) ;
1794-
1795- fn get_deref_type_and_refs ( mut ty : Ty < ' _ > ) -> ( Ty < ' _ > , usize ) {
1796- let mut refs = 0 ;
1797-
1798- while let ty:: Ref ( _, new_ty, _) = ty. kind ( ) {
1799- ty = * new_ty;
1800- refs += 1 ;
1801- }
1802-
1803- ( ty, refs)
1804- }
1805-
1806- for ( ( found_arg, expected_arg) , arg_span) in
1807- found_args. zip ( expected_args) . zip ( arg_spans)
1808- {
1809- let ( found_ty, found_refs) = get_deref_type_and_refs ( * found_arg) ;
1810- let ( expected_ty, expected_refs) = get_deref_type_and_refs ( * expected_arg) ;
1811-
1812- if found_ty == expected_ty {
1813- let hint = if found_refs < expected_refs {
1814- "consider borrowing here:"
1815- } else if found_refs == expected_refs {
1816- continue ;
1817- } else {
1818- "consider removing the borrow:"
1819- } ;
1820- err. span_suggestion_verbose (
1821- arg_span,
1822- hint,
1823- expected_arg. to_string ( ) ,
1824- Applicability :: MaybeIncorrect ,
1825- ) ;
1826- }
1827- }
1762+ hint_missing_borrow ( span, found_span, found, expected, found_node, & mut err) ;
18281763 }
18291764
18301765 err
@@ -3455,6 +3390,81 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
34553390 }
34563391}
34573392
3393+ /// Add a hint to add a missing borrow or remove an unnecessary one.
3394+ fn hint_missing_borrow < ' tcx > (
3395+ span : Span ,
3396+ found_span : Span ,
3397+ found : Ty < ' tcx > ,
3398+ expected : Ty < ' tcx > ,
3399+ found_node : Node < ' _ > ,
3400+ err : & mut Diagnostic ,
3401+ ) {
3402+ let found_args = match found. kind ( ) {
3403+ ty:: FnPtr ( f) => f. inputs ( ) . skip_binder ( ) . iter ( ) ,
3404+ kind => {
3405+ span_bug ! ( span, "found was converted to a FnPtr above but is now {:?}" , kind)
3406+ }
3407+ } ;
3408+ let expected_args = match expected. kind ( ) {
3409+ ty:: FnPtr ( f) => f. inputs ( ) . skip_binder ( ) . iter ( ) ,
3410+ kind => {
3411+ span_bug ! ( span, "expected was converted to a FnPtr above but is now {:?}" , kind)
3412+ }
3413+ } ;
3414+
3415+ let fn_decl = match found_node {
3416+ Node :: Expr ( expr) => match & expr. kind {
3417+ hir:: ExprKind :: Closure ( hir:: Closure { fn_decl, .. } ) => fn_decl,
3418+ kind => {
3419+ span_bug ! ( found_span, "expression must be a closure but is {:?}" , kind)
3420+ }
3421+ } ,
3422+ Node :: Item ( item) => match & item. kind {
3423+ hir:: ItemKind :: Fn ( signature, _generics, _body) => signature. decl ,
3424+ kind => {
3425+ span_bug ! ( found_span, "item must be a function but is {:?}" , kind)
3426+ }
3427+ } ,
3428+ node => {
3429+ span_bug ! ( found_span, "node must be a expr or item but is {:?}" , node)
3430+ }
3431+ } ;
3432+
3433+ let arg_spans = fn_decl. inputs . iter ( ) . map ( |ty| ty. span ) ;
3434+
3435+ fn get_deref_type_and_refs < ' tcx > ( mut ty : Ty < ' tcx > ) -> ( Ty < ' tcx > , usize ) {
3436+ let mut refs = 0 ;
3437+
3438+ while let ty:: Ref ( _, new_ty, _) = ty. kind ( ) {
3439+ ty = * new_ty;
3440+ refs += 1 ;
3441+ }
3442+
3443+ ( ty, refs)
3444+ }
3445+
3446+ for ( ( found_arg, expected_arg) , arg_span) in found_args. zip ( expected_args) . zip ( arg_spans) {
3447+ let ( found_ty, found_refs) = get_deref_type_and_refs ( * found_arg) ;
3448+ let ( expected_ty, expected_refs) = get_deref_type_and_refs ( * expected_arg) ;
3449+
3450+ if found_ty == expected_ty {
3451+ let hint = if found_refs < expected_refs {
3452+ "consider borrowing here:"
3453+ } else if found_refs == expected_refs {
3454+ continue ;
3455+ } else {
3456+ "consider removing the borrow:"
3457+ } ;
3458+ err. span_suggestion_verbose (
3459+ arg_span,
3460+ hint,
3461+ expected_arg. to_string ( ) ,
3462+ Applicability :: MaybeIncorrect ,
3463+ ) ;
3464+ }
3465+ }
3466+ }
3467+
34583468/// Collect all the returned expressions within the input expression.
34593469/// Used to point at the return spans when we want to suggest some change to them.
34603470#[ derive( Default ) ]
0 commit comments