@@ -258,6 +258,7 @@ pub trait TypeErrCtxtExt<'tcx> {
258
258
found : ty:: PolyTraitRef < ' tcx > ,
259
259
expected : ty:: PolyTraitRef < ' tcx > ,
260
260
cause : & ObligationCauseCode < ' tcx > ,
261
+ found_node : Option < Node < ' _ > > ,
261
262
) -> DiagnosticBuilder < ' tcx , ErrorGuaranteed > ;
262
263
263
264
fn note_conflicting_closure_bounds (
@@ -1695,6 +1696,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
1695
1696
found : ty:: PolyTraitRef < ' tcx > ,
1696
1697
expected : ty:: PolyTraitRef < ' tcx > ,
1697
1698
cause : & ObligationCauseCode < ' tcx > ,
1699
+ found_node : Option < Node < ' _ > > ,
1698
1700
) -> DiagnosticBuilder < ' tcx , ErrorGuaranteed > {
1699
1701
pub ( crate ) fn build_fn_sig_ty < ' tcx > (
1700
1702
infcx : & InferCtxt < ' tcx > ,
@@ -1756,6 +1758,75 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
1756
1758
1757
1759
self . note_conflicting_closure_bounds ( cause, & mut err) ;
1758
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
+ 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
+ "hint: consider borrowing here:"
1815
+ } else if found_refs == expected_refs {
1816
+ continue ;
1817
+ } else {
1818
+ "hint: 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
+ }
1828
+ }
1829
+
1759
1830
err
1760
1831
}
1761
1832
0 commit comments