@@ -1758,73 +1758,8 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
1758
1758
1759
1759
self . note_conflicting_closure_bounds ( cause, & mut err) ;
1760
1760
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
-
1774
1761
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) ;
1828
1763
}
1829
1764
1830
1765
err
@@ -3455,6 +3390,81 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
3455
3390
}
3456
3391
}
3457
3392
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
+
3458
3468
/// Collect all the returned expressions within the input expression.
3459
3469
/// Used to point at the return spans when we want to suggest some change to them.
3460
3470
#[ derive( Default ) ]
0 commit comments