@@ -283,6 +283,7 @@ pub trait TypeErrCtxtExt<'tcx> {
283283 expected : ty:: PolyTraitRef < ' tcx > ,
284284 cause : & ObligationCauseCode < ' tcx > ,
285285 found_node : Option < Node < ' _ > > ,
286+ param_env : ty:: ParamEnv < ' tcx > ,
286287 ) -> DiagnosticBuilder < ' tcx , ErrorGuaranteed > ;
287288
288289 fn note_conflicting_closure_bounds (
@@ -1978,6 +1979,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
19781979 expected : ty:: PolyTraitRef < ' tcx > ,
19791980 cause : & ObligationCauseCode < ' tcx > ,
19801981 found_node : Option < Node < ' _ > > ,
1982+ param_env : ty:: ParamEnv < ' tcx > ,
19811983 ) -> DiagnosticBuilder < ' tcx , ErrorGuaranteed > {
19821984 pub ( crate ) fn build_fn_sig_ty < ' tcx > (
19831985 infcx : & InferCtxt < ' tcx > ,
@@ -2040,7 +2042,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
20402042 self . note_conflicting_closure_bounds ( cause, & mut err) ;
20412043
20422044 if let Some ( found_node) = found_node {
2043- hint_missing_borrow ( span, found, expected, found_node, & mut err) ;
2045+ hint_missing_borrow ( self , param_env , span, found, expected, found_node, & mut err) ;
20442046 }
20452047
20462048 err
@@ -3747,6 +3749,8 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
37473749
37483750/// Add a hint to add a missing borrow or remove an unnecessary one.
37493751fn hint_missing_borrow < ' tcx > (
3752+ infcx : & InferCtxt < ' tcx > ,
3753+ param_env : ty:: ParamEnv < ' tcx > ,
37503754 span : Span ,
37513755 found : Ty < ' tcx > ,
37523756 expected : Ty < ' tcx > ,
@@ -3769,7 +3773,7 @@ fn hint_missing_borrow<'tcx>(
37693773 // This could be a variant constructor, for example.
37703774 let Some ( fn_decl) = found_node. fn_decl ( ) else { return ; } ;
37713775
3772- let arg_spans = fn_decl. inputs . iter ( ) . map ( |ty| ty. span ) ;
3776+ let args = fn_decl. inputs . iter ( ) . map ( |ty| ty) ;
37733777
37743778 fn get_deref_type_and_refs ( mut ty : Ty < ' _ > ) -> ( Ty < ' _ > , usize ) {
37753779 let mut refs = 0 ;
@@ -3785,29 +3789,42 @@ fn hint_missing_borrow<'tcx>(
37853789 let mut to_borrow = Vec :: new ( ) ;
37863790 let mut remove_borrow = Vec :: new ( ) ;
37873791
3788- for ( ( found_arg, expected_arg) , arg_span ) in found_args. zip ( expected_args) . zip ( arg_spans ) {
3792+ for ( ( found_arg, expected_arg) , arg ) in found_args. zip ( expected_args) . zip ( args ) {
37893793 let ( found_ty, found_refs) = get_deref_type_and_refs ( * found_arg) ;
37903794 let ( expected_ty, expected_refs) = get_deref_type_and_refs ( * expected_arg) ;
37913795
3792- if found_ty == expected_ty {
3796+ if infcx . can_eq ( param_env , found_ty, expected_ty) . is_ok ( ) {
37933797 if found_refs < expected_refs {
3794- to_borrow. push ( ( arg_span , expected_arg . to_string ( ) ) ) ;
3798+ to_borrow. push ( ( arg . span . shrink_to_lo ( ) , "&" . repeat ( expected_refs - found_refs ) ) ) ;
37953799 } else if found_refs > expected_refs {
3796- remove_borrow. push ( ( arg_span, expected_arg. to_string ( ) ) ) ;
3800+ let mut span = arg. span . shrink_to_lo ( ) ;
3801+ let mut left = found_refs - expected_refs;
3802+ let mut ty = arg;
3803+ while let hir:: TyKind :: Ref ( _, mut_ty) = & ty. kind && left > 0 {
3804+ span = span. with_hi ( mut_ty. ty . span . lo ( ) ) ;
3805+ ty = mut_ty. ty ;
3806+ left -= 1 ;
3807+ }
3808+ let sugg = if left == 0 {
3809+ ( span, String :: new ( ) )
3810+ } else {
3811+ ( arg. span , expected_arg. to_string ( ) )
3812+ } ;
3813+ remove_borrow. push ( sugg) ;
37973814 }
37983815 }
37993816 }
38003817
38013818 if !to_borrow. is_empty ( ) {
3802- err. multipart_suggestion (
3819+ err. multipart_suggestion_verbose (
38033820 "consider borrowing the argument" ,
38043821 to_borrow,
38053822 Applicability :: MaybeIncorrect ,
38063823 ) ;
38073824 }
38083825
38093826 if !remove_borrow. is_empty ( ) {
3810- err. multipart_suggestion (
3827+ err. multipart_suggestion_verbose (
38113828 "do not borrow the argument" ,
38123829 remove_borrow,
38133830 Applicability :: MaybeIncorrect ,
0 commit comments