@@ -1657,73 +1657,8 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
16571657
16581658 self . note_conflicting_closure_bounds ( cause, & mut err) ;
16591659
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-
16731660 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) ;
17271662 }
17281663
17291664 err
@@ -3108,6 +3043,81 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
31083043 }
31093044}
31103045
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+
31113121/// Collect all the returned expressions within the input expression.
31123122/// Used to point at the return spans when we want to suggest some change to them.
31133123#[ derive( Default ) ]
0 commit comments