@@ -10,7 +10,7 @@ use rustc_middle::ty::adjustment::{
1010 Adjust , Adjustment , AllowTwoPhase , AutoBorrow , AutoBorrowMutability ,
1111} ;
1212use rustc_middle:: ty:: TyKind :: { Adt , Array , Char , FnDef , Never , Ref , Str , Tuple , Uint } ;
13- use rustc_middle:: ty:: { self , suggest_constraining_type_param, Ty , TypeFoldable } ;
13+ use rustc_middle:: ty:: { self , suggest_constraining_type_param, Ty , TyCtxt , TypeFoldable } ;
1414use rustc_span:: Span ;
1515use rustc_trait_selection:: infer:: InferCtxtExt ;
1616
@@ -254,49 +254,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
254254 if !lhs_ty. references_error ( ) {
255255 let source_map = self . tcx . sess . source_map ( ) ;
256256
257- let suggest_constraining_param =
258- |mut err : & mut DiagnosticBuilder < ' _ > ,
259- missing_trait : & str ,
260- p : ty:: ParamTy ,
261- set_output : bool | {
262- let hir = self . tcx . hir ( ) ;
263- let msg =
264- & format ! ( "`{}` might need a bound for `{}`" , lhs_ty, missing_trait) ;
265- if let Some ( def_id) = hir
266- . find ( hir. get_parent_item ( expr. hir_id ) )
267- . and_then ( |node| node. hir_id ( ) )
268- . and_then ( |hir_id| hir. opt_local_def_id ( hir_id) )
269- {
270- let generics = self . tcx . generics_of ( def_id) ;
271- let param_def_id = generics. type_param ( & p, self . tcx ) . def_id ;
272- if let Some ( generics) = hir
273- . as_local_hir_id ( param_def_id)
274- . and_then ( |id| hir. find ( hir. get_parent_item ( id) ) )
275- . as_ref ( )
276- . and_then ( |node| node. generics ( ) )
277- {
278- let output = if set_output {
279- format ! ( "<Output = {}>" , rhs_ty)
280- } else {
281- String :: new ( )
282- } ;
283- suggest_constraining_type_param (
284- self . tcx ,
285- generics,
286- & mut err,
287- & format ! ( "{}" , lhs_ty) ,
288- & format ! ( "{}{}" , missing_trait, output) ,
289- None ,
290- ) ;
291- } else {
292- let span = self . tcx . def_span ( param_def_id) ;
293- err. span_label ( span, msg) ;
294- }
295- } else {
296- err. note ( & msg) ;
297- }
298- } ;
299-
300257 match is_assign {
301258 IsAssign :: Yes => {
302259 let mut err = struct_span_err ! (
@@ -362,7 +319,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
362319 // concatenation (e.g., "Hello " += "World!"). This means
363320 // we don't want the note in the else clause to be emitted
364321 } else if let ty:: Param ( p) = lhs_ty. kind {
365- suggest_constraining_param ( & mut err, missing_trait, p, false ) ;
322+ suggest_constraining_param (
323+ self . tcx ,
324+ & mut err,
325+ lhs_ty,
326+ rhs_ty,
327+ & expr,
328+ missing_trait,
329+ p,
330+ false ,
331+ ) ;
366332 } else if !suggested_deref {
367333 suggest_impl_missing ( & mut err, lhs_ty, & missing_trait) ;
368334 }
@@ -514,7 +480,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
514480 // we don't want the note in the else clause to be emitted
515481 } else if let ty:: Param ( p) = lhs_ty. kind {
516482 suggest_constraining_param (
483+ self . tcx ,
517484 & mut err,
485+ lhs_ty,
486+ rhs_ty,
487+ & expr,
518488 missing_trait,
519489 p,
520490 use_output,
@@ -965,3 +935,49 @@ fn suggest_impl_missing(err: &mut DiagnosticBuilder<'_>, ty: Ty<'_>, missing_tra
965935 }
966936 }
967937}
938+
939+ fn suggest_constraining_param (
940+ tcx : TyCtxt < ' _ > ,
941+ mut err : & mut DiagnosticBuilder < ' _ > ,
942+ lhs_ty : Ty < ' _ > ,
943+ rhs_ty : Ty < ' _ > ,
944+ expr : & hir:: Expr < ' _ > ,
945+ missing_trait : & str ,
946+ p : ty:: ParamTy ,
947+ set_output : bool ,
948+ ) {
949+ let hir = tcx. hir ( ) ;
950+ let msg = & format ! ( "`{}` might need a bound for `{}`" , lhs_ty, missing_trait) ;
951+ // Try to find the def-id and details for the parameter p. We have only the index,
952+ // so we have to find the enclosing function's def-id, then look through its declared
953+ // generic parameters to get the declaration.
954+ if let Some ( def_id) = hir
955+ . find ( hir. get_parent_item ( expr. hir_id ) )
956+ . and_then ( |node| node. hir_id ( ) )
957+ . and_then ( |hir_id| hir. opt_local_def_id ( hir_id) )
958+ {
959+ let generics = tcx. generics_of ( def_id) ;
960+ let param_def_id = generics. type_param ( & p, tcx) . def_id ;
961+ if let Some ( generics) = hir
962+ . as_local_hir_id ( param_def_id)
963+ . and_then ( |id| hir. find ( hir. get_parent_item ( id) ) )
964+ . as_ref ( )
965+ . and_then ( |node| node. generics ( ) )
966+ {
967+ let output = if set_output { format ! ( "<Output = {}>" , rhs_ty) } else { String :: new ( ) } ;
968+ suggest_constraining_type_param (
969+ tcx,
970+ generics,
971+ & mut err,
972+ & format ! ( "{}" , lhs_ty) ,
973+ & format ! ( "{}{}" , missing_trait, output) ,
974+ None ,
975+ ) ;
976+ } else {
977+ let span = tcx. def_span ( param_def_id) ;
978+ err. span_label ( span, msg) ;
979+ }
980+ } else {
981+ err. note ( & msg) ;
982+ }
983+ }
0 commit comments