@@ -255,6 +255,7 @@ pub trait TypeErrCtxtExt<'tcx> {
255
255
found : ty:: PolyTraitRef < ' tcx > ,
256
256
expected : ty:: PolyTraitRef < ' tcx > ,
257
257
cause : & ObligationCauseCode < ' tcx > ,
258
+ found_node : Option < Node < ' _ > > ,
258
259
) -> DiagnosticBuilder < ' tcx , ErrorGuaranteed > ;
259
260
260
261
fn note_conflicting_closure_bounds (
@@ -1592,6 +1593,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
1592
1593
found : ty:: PolyTraitRef < ' tcx > ,
1593
1594
expected : ty:: PolyTraitRef < ' tcx > ,
1594
1595
cause : & ObligationCauseCode < ' tcx > ,
1596
+ found_node : Option < Node < ' _ > > ,
1595
1597
) -> DiagnosticBuilder < ' tcx , ErrorGuaranteed > {
1596
1598
pub ( crate ) fn build_fn_sig_ty < ' tcx > (
1597
1599
infcx : & InferCtxt < ' tcx > ,
@@ -1655,6 +1657,75 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
1655
1657
1656
1658
self . note_conflicting_closure_bounds ( cause, & mut err) ;
1657
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
+ 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
+ "hint: consider borrowing here:"
1714
+ } else if found_refs == expected_refs {
1715
+ continue ;
1716
+ } else {
1717
+ "hint: 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
+ }
1727
+ }
1728
+
1658
1729
err
1659
1730
}
1660
1731
0 commit comments