@@ -15,11 +15,13 @@ use rustc_hir as hir;
1515use  rustc_hir:: def_id:: { DefId ,  LocalDefId } ; 
1616use  rustc_infer:: traits:: FulfillmentError ; 
1717use  rustc_middle:: query:: Key ; 
18- use  rustc_middle:: ty:: { self ,  suggest_constraining_type_param,  Ty ,  TyCtxt ,  TypeVisitableExt } ; 
18+ use  rustc_middle:: ty:: { 
19+     self ,  suggest_constraining_type_param,  GenericParamCount ,  Ty ,  TyCtxt ,  TypeVisitableExt , 
20+ } ; 
1921use  rustc_session:: parse:: feature_err; 
2022use  rustc_span:: edit_distance:: find_best_match_for_name; 
2123use  rustc_span:: symbol:: { sym,  Ident } ; 
22- use  rustc_span:: { Span ,  Symbol ,  DUMMY_SP } ; 
24+ use  rustc_span:: { BytePos ,   Span ,  Symbol ,  DUMMY_SP } ; 
2325use  rustc_trait_selection:: traits:: object_safety_violations_for_assoc_item; 
2426
2527impl < ' tcx >  dyn  AstConv < ' tcx >  + ' _  { 
@@ -1029,12 +1031,12 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
10291031/// Emits an error regarding forbidden type binding associations 
10301032pub  fn  prohibit_assoc_ty_binding ( 
10311033    tcx :  TyCtxt < ' _ > , 
1032-     span :   Span , 
1033-     segment :  Option < ( & hir:: PathSegment < ' _ > ,  Span ) > , 
1034+     binding :   & hir :: TypeBinding < ' _ > , 
1035+     segment :  Option < ( DefId ,   & hir:: PathSegment < ' _ > ,  Span ) > , 
10341036)  { 
1035-     tcx. dcx ( ) . emit_err ( AssocTypeBindingNotAllowed  { 
1036-         span, 
1037-         fn_trait_expansion :  if  let  Some ( ( segment,  span) )  = segment
1037+     let   mut  err =  tcx. dcx ( ) . create_err ( AssocTypeBindingNotAllowed  { 
1038+         span :  binding . span , 
1039+         fn_trait_expansion :  if  let  Some ( ( _ ,   segment,  span) )  = segment
10381040            && segment. args ( ) . parenthesized  == hir:: GenericArgsParentheses :: ParenSugar 
10391041        { 
10401042            Some ( ParenthesizedFnTraitExpansion  { 
@@ -1045,6 +1047,78 @@ pub fn prohibit_assoc_ty_binding(
10451047            None 
10461048        } , 
10471049    } ) ; 
1050+ 
1051+     // Emit a suggestion if possible 
1052+     if  let  Some ( ( def_id,  segment,  _) )  = segment
1053+         && segment. args ( ) . parenthesized  == hir:: GenericArgsParentheses :: No 
1054+         && let  hir:: TypeBindingKind :: Equality  {  term :  binding_arg_ty }  = binding. kind 
1055+     { 
1056+         // Suggests removal of the offending equality constraint 
1057+         let  suggest_removal = |e :  & mut  Diag < ' _ > | { 
1058+             let  mut  suggestion_span = binding. span . with_hi ( binding. span . hi ( )  + BytePos ( 1 ) ) ;  // Include the comma or the angle bracket at the end 
1059+             if  segment. args ( ) . bindings . len ( )  == 1  { 
1060+                 // If it is the only binding specified 
1061+                 // include the starting angle bracket as well 
1062+                 suggestion_span = suggestion_span. with_lo ( suggestion_span. lo ( )  - BytePos ( 1 ) ) 
1063+             } 
1064+             if  let  Ok ( suggestion)  = tcx. sess . source_map ( ) . span_to_snippet ( suggestion_span)  { 
1065+                 e. span_suggestion_verbose ( 
1066+                     suggestion_span, 
1067+                     "try removing this type binding" , 
1068+                     suggestion, 
1069+                     Applicability :: MaybeIncorrect , 
1070+                 ) ; 
1071+             } 
1072+         } ; 
1073+ 
1074+         // Suggests replacing the quality constraint with 
1075+         // normal type argument 
1076+         let  suggest_direct_use = |e :  & mut  Diag < ' _ > ,  sp :  Span ,  is_ty :  bool | { 
1077+             if  let  Ok ( snippet)  = tcx. sess . source_map ( ) . span_to_snippet ( sp)  { 
1078+                 let  ty_or_const = if  is_ty {  "generic"  }  else  {  "const"  } ; 
1079+                 e. span_suggestion_verbose ( 
1080+                     binding. span , 
1081+                     format ! ( "to use `{snippet}` as a {ty_or_const} argument specify it directly" ) , 
1082+                     snippet, 
1083+                     Applicability :: MaybeIncorrect , 
1084+                 ) ; 
1085+             } 
1086+         } ; 
1087+ 
1088+         // Get a sense of what generic args the type expects 
1089+         let  generics = tcx. generics_of ( def_id) ; 
1090+         let  GenericParamCount  {  mut  types,  consts,  .. }  = generics. own_counts ( ) ; 
1091+         if  generics. has_self  { 
1092+             types -= 1  // Ignore the `Self` type 
1093+         } 
1094+ 
1095+         // Now emit suggestion 
1096+         if  types == 0  && consts == 0  { 
1097+             err. note ( format ! ( "`{0}` is not a generic type" ,  segment. ident) ) ; 
1098+             suggest_removal ( & mut  err) ; 
1099+         }  else  { 
1100+             match  binding_arg_ty { 
1101+                 hir:: Term :: Ty ( ty)  => { 
1102+                     if  types > 0  { 
1103+                         suggest_direct_use ( & mut  err,  ty. span ,  true ) ; 
1104+                     }  else  { 
1105+                         suggest_removal ( & mut  err) ; 
1106+                     } 
1107+                 } 
1108+                 hir:: Term :: Const ( c)  if  consts > 0  => { 
1109+                     if  consts > 0  { 
1110+                         let  span = tcx. hir ( ) . span ( c. hir_id ) ; 
1111+                         suggest_direct_use ( & mut  err,  span,  false ) ; 
1112+                     }  else  { 
1113+                         suggest_removal ( & mut  err) ; 
1114+                     } 
1115+                 } 
1116+                 _ => { } 
1117+             } 
1118+         } 
1119+     } 
1120+ 
1121+     err. emit ( ) ; 
10481122} 
10491123
10501124pub ( crate )  fn  fn_trait_to_string ( 
0 commit comments