@@ -1657,73 +1657,8 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
1657
1657
1658
1658
self . note_conflicting_closure_bounds ( cause, & mut err) ;
1659
1659
1660
- let found_args = match found. kind ( ) {
1661
- ty:: FnPtr ( f) => f. inputs ( ) . skip_binder ( ) . iter ( ) ,
1662
- kind => {
1663
- span_bug ! ( span, "found was converted to a FnPtr above but is now {:?}" , kind)
1664
- }
1665
- } ;
1666
- let expected_args = match expected. kind ( ) {
1667
- ty:: FnPtr ( f) => f. inputs ( ) . skip_binder ( ) . iter ( ) ,
1668
- kind => {
1669
- span_bug ! ( span, "expected was converted to a FnPtr above but is now {:?}" , kind)
1670
- }
1671
- } ;
1672
-
1673
1660
if let Some ( found_node) = found_node {
1674
- let fn_decl = match found_node {
1675
- Node :: Expr ( expr) => match & expr. kind {
1676
- hir:: ExprKind :: Closure ( hir:: Closure { fn_decl, .. } ) => fn_decl,
1677
- kind => {
1678
- span_bug ! ( found_span, "expression must be a closure but is {:?}" , kind)
1679
- }
1680
- } ,
1681
- Node :: Item ( item) => match & item. kind {
1682
- hir:: ItemKind :: Fn ( signature, _generics, _body) => signature. decl ,
1683
- kind => {
1684
- span_bug ! ( found_span, "item must be a function but is {:?}" , kind)
1685
- }
1686
- } ,
1687
- node => {
1688
- span_bug ! ( found_span, "node must be a expr or item but is {:?}" , node)
1689
- }
1690
- } ;
1691
-
1692
- let arg_spans = fn_decl. inputs . iter ( ) . map ( |ty| ty. span ) ;
1693
-
1694
- fn get_deref_type_and_refs ( mut ty : Ty < ' _ > ) -> ( Ty < ' _ > , usize ) {
1695
- let mut refs = 0 ;
1696
-
1697
- while let ty:: Ref ( _, new_ty, _) = ty. kind ( ) {
1698
- ty = * new_ty;
1699
- refs += 1 ;
1700
- }
1701
-
1702
- ( ty, refs)
1703
- }
1704
-
1705
- for ( ( found_arg, expected_arg) , arg_span) in
1706
- found_args. zip ( expected_args) . zip ( arg_spans)
1707
- {
1708
- let ( found_ty, found_refs) = get_deref_type_and_refs ( * found_arg) ;
1709
- let ( expected_ty, expected_refs) = get_deref_type_and_refs ( * expected_arg) ;
1710
-
1711
- if found_ty == expected_ty {
1712
- let hint = if found_refs < expected_refs {
1713
- "consider borrowing here:"
1714
- } else if found_refs == expected_refs {
1715
- continue ;
1716
- } else {
1717
- "consider removing the borrow:"
1718
- } ;
1719
- err. span_suggestion_verbose (
1720
- arg_span,
1721
- hint,
1722
- expected_arg. to_string ( ) ,
1723
- Applicability :: MaybeIncorrect ,
1724
- ) ;
1725
- }
1726
- }
1661
+ hint_missing_borrow ( span, found_span, found, expected, found_node, & mut err) ;
1727
1662
}
1728
1663
1729
1664
err
@@ -3108,6 +3043,81 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
3108
3043
}
3109
3044
}
3110
3045
3046
+ /// Add a hint to add a missing borrow or remove an unnecessary one.
3047
+ fn hint_missing_borrow < ' tcx > (
3048
+ span : Span ,
3049
+ found_span : Span ,
3050
+ found : Ty < ' tcx > ,
3051
+ expected : Ty < ' tcx > ,
3052
+ found_node : Node < ' _ > ,
3053
+ err : & mut Diagnostic ,
3054
+ ) {
3055
+ let found_args = match found. kind ( ) {
3056
+ ty:: FnPtr ( f) => f. inputs ( ) . skip_binder ( ) . iter ( ) ,
3057
+ kind => {
3058
+ span_bug ! ( span, "found was converted to a FnPtr above but is now {:?}" , kind)
3059
+ }
3060
+ } ;
3061
+ let expected_args = match expected. kind ( ) {
3062
+ ty:: FnPtr ( f) => f. inputs ( ) . skip_binder ( ) . iter ( ) ,
3063
+ kind => {
3064
+ span_bug ! ( span, "expected was converted to a FnPtr above but is now {:?}" , kind)
3065
+ }
3066
+ } ;
3067
+
3068
+ let fn_decl = match found_node {
3069
+ Node :: Expr ( expr) => match & expr. kind {
3070
+ hir:: ExprKind :: Closure ( hir:: Closure { fn_decl, .. } ) => fn_decl,
3071
+ kind => {
3072
+ span_bug ! ( found_span, "expression must be a closure but is {:?}" , kind)
3073
+ }
3074
+ } ,
3075
+ Node :: Item ( item) => match & item. kind {
3076
+ hir:: ItemKind :: Fn ( signature, _generics, _body) => signature. decl ,
3077
+ kind => {
3078
+ span_bug ! ( found_span, "item must be a function but is {:?}" , kind)
3079
+ }
3080
+ } ,
3081
+ node => {
3082
+ span_bug ! ( found_span, "node must be a expr or item but is {:?}" , node)
3083
+ }
3084
+ } ;
3085
+
3086
+ let arg_spans = fn_decl. inputs . iter ( ) . map ( |ty| ty. span ) ;
3087
+
3088
+ fn get_deref_type_and_refs < ' tcx > ( mut ty : Ty < ' tcx > ) -> ( Ty < ' tcx > , usize ) {
3089
+ let mut refs = 0 ;
3090
+
3091
+ while let ty:: Ref ( _, new_ty, _) = ty. kind ( ) {
3092
+ ty = * new_ty;
3093
+ refs += 1 ;
3094
+ }
3095
+
3096
+ ( ty, refs)
3097
+ }
3098
+
3099
+ for ( ( found_arg, expected_arg) , arg_span) in found_args. zip ( expected_args) . zip ( arg_spans) {
3100
+ let ( found_ty, found_refs) = get_deref_type_and_refs ( * found_arg) ;
3101
+ let ( expected_ty, expected_refs) = get_deref_type_and_refs ( * expected_arg) ;
3102
+
3103
+ if found_ty == expected_ty {
3104
+ let hint = if found_refs < expected_refs {
3105
+ "consider borrowing here:"
3106
+ } else if found_refs == expected_refs {
3107
+ continue ;
3108
+ } else {
3109
+ "consider removing the borrow:"
3110
+ } ;
3111
+ err. span_suggestion_verbose (
3112
+ arg_span,
3113
+ hint,
3114
+ expected_arg. to_string ( ) ,
3115
+ Applicability :: MaybeIncorrect ,
3116
+ ) ;
3117
+ }
3118
+ }
3119
+ }
3120
+
3111
3121
/// Collect all the returned expressions within the input expression.
3112
3122
/// Used to point at the return spans when we want to suggest some change to them.
3113
3123
#[ derive( Default ) ]
0 commit comments