@@ -255,6 +255,7 @@ pub trait TypeErrCtxtExt<'tcx> {
255255 found : ty:: PolyTraitRef < ' tcx > ,
256256 expected : ty:: PolyTraitRef < ' tcx > ,
257257 cause : & ObligationCauseCode < ' tcx > ,
258+ found_node : Option < Node < ' _ > > ,
258259 ) -> DiagnosticBuilder < ' tcx , ErrorGuaranteed > ;
259260
260261 fn note_conflicting_closure_bounds (
@@ -1592,6 +1593,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
15921593 found : ty:: PolyTraitRef < ' tcx > ,
15931594 expected : ty:: PolyTraitRef < ' tcx > ,
15941595 cause : & ObligationCauseCode < ' tcx > ,
1596+ found_node : Option < Node < ' _ > > ,
15951597 ) -> DiagnosticBuilder < ' tcx , ErrorGuaranteed > {
15961598 pub ( crate ) fn build_fn_sig_ty < ' tcx > (
15971599 infcx : & InferCtxt < ' tcx > ,
@@ -1655,6 +1657,75 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
16551657
16561658 self . note_conflicting_closure_bounds ( cause, & mut err) ;
16571659
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+
16581729 err
16591730 }
16601731
0 commit comments