22
33use  crate :: infer:: error_reporting:: nice_region_error:: NiceRegionError ; 
44use  crate :: infer:: lexical_region_resolve:: RegionResolutionError ; 
5- use  crate :: infer:: { Subtype ,  ValuePairs } ; 
5+ use  crate :: infer:: { Subtype ,  TyCtxtInferExt ,   ValuePairs } ; 
66use  crate :: traits:: ObligationCauseCode :: CompareImplMethodObligation ; 
77use  rustc_errors:: ErrorReported ; 
8- use  rustc_middle:: ty:: Ty ; 
9- use  rustc_span:: Span ; 
8+ use  rustc_hir as  hir; 
9+ use  rustc_hir:: def:: Res ; 
10+ use  rustc_hir:: def_id:: DefId ; 
11+ use  rustc_hir:: intravisit:: Visitor ; 
12+ use  rustc_middle:: ty:: error:: ExpectedFound ; 
13+ use  rustc_middle:: ty:: { self ,  Ty ,  TyCtxt } ; 
14+ use  rustc_span:: { MultiSpan ,  Span } ; 
1015
1116impl < ' a ,  ' tcx >  NiceRegionError < ' a ,  ' tcx >  { 
1217    /// Print the error message for lifetime errors when the `impl` doesn't conform to the `trait`. 
@@ -36,7 +41,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
3641                                var_origin. span ( ) , 
3742                                sub_expected_found. expected , 
3843                                sub_expected_found. found , 
39-                                 self . tcx ( ) . def_span ( * trait_item_def_id) , 
44+                                 * trait_item_def_id, 
4045                            ) ; 
4146                            return  Some ( ErrorReported ) ; 
4247                        } 
@@ -47,14 +52,100 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
4752        None 
4853    } 
4954
50-     fn  emit_err ( & self ,  sp :  Span ,  expected :  Ty < ' tcx > ,  found :  Ty < ' tcx > ,  impl_sp :  Span )  { 
55+     fn  emit_err ( & self ,  sp :  Span ,  expected :  Ty < ' tcx > ,  found :  Ty < ' tcx > ,  trait_def_id :  DefId )  { 
56+         let  tcx = self . tcx ( ) ; 
57+         let  trait_sp = self . tcx ( ) . def_span ( trait_def_id) ; 
5158        let  mut  err = self 
5259            . tcx ( ) 
5360            . sess 
5461            . struct_span_err ( sp,  "`impl` item signature doesn't match `trait` item signature" ) ; 
55-         err. note ( & format ! ( "expected `{:?}`\n    found `{:?}`" ,  expected,  found) ) ; 
56-         err. span_label ( sp,  & format ! ( "found {:?}" ,  found) ) ; 
57-         err. span_label ( impl_sp,  & format ! ( "expected {:?}" ,  expected) ) ; 
62+         err. span_label ( sp,  & format ! ( "found `{:?}`" ,  found) ) ; 
63+         err. span_label ( trait_sp,  & format ! ( "expected `{:?}`" ,  expected) ) ; 
64+ 
65+         // Get the span of all the used type parameters in the method. 
66+         let  assoc_item = self . tcx ( ) . associated_item ( trait_def_id) ; 
67+         let  mut  visitor = TypeParamSpanVisitor  {  tcx :  self . tcx ( ) ,  types :  vec ! [ ]  } ; 
68+         match  assoc_item. kind  { 
69+             ty:: AssocKind :: Fn  => { 
70+                 let  hir = self . tcx ( ) . hir ( ) ; 
71+                 if  let  Some ( hir_id)  = assoc_item. def_id . as_local ( ) . map ( |id| hir. as_local_hir_id ( id) ) 
72+                 { 
73+                     if  let  Some ( decl)  = hir. fn_decl_by_hir_id ( hir_id)  { 
74+                         visitor. visit_fn_decl ( decl) ; 
75+                     } 
76+                 } 
77+             } 
78+             _ => { } 
79+         } 
80+         let  mut  type_param_span:  MultiSpan  =
81+             visitor. types . iter ( ) . cloned ( ) . collect :: < Vec < _ > > ( ) . into ( ) ; 
82+         for  & span in  & visitor. types  { 
83+             type_param_span. push_span_label ( 
84+                 span, 
85+                 "consider borrowing this type parameter in the trait" . to_string ( ) , 
86+             ) ; 
87+         } 
88+ 
89+         if  let  Some ( ( expected,  found) )  = tcx
90+             . infer_ctxt ( ) 
91+             . enter ( |infcx| infcx. expected_found_str_ty ( & ExpectedFound  {  expected,  found } ) ) 
92+         { 
93+             // Highlighted the differences when showing the "expected/found" note. 
94+             err. note_expected_found ( & "" ,  expected,  & "" ,  found) ; 
95+         }  else  { 
96+             // This fallback shouldn't be necessary, but let's keep it in just in case. 
97+             err. note ( & format ! ( "expected `{:?}`\n    found `{:?}`" ,  expected,  found) ) ; 
98+         } 
99+         err. span_help ( 
100+             type_param_span, 
101+             "the lifetime requirements from the `impl` do not correspond to the requirements in \  
102+ , 
103+         ) ; 
104+         if  visitor. types . is_empty ( )  { 
105+             err. help ( 
106+                 "verify the lifetime relationships in the `trait` and `impl` between the `self` \  
107+ , 
108+             ) ; 
109+         } 
58110        err. emit ( ) ; 
59111    } 
60112} 
113+ 
114+ struct  TypeParamSpanVisitor < ' tcx >  { 
115+     tcx :  TyCtxt < ' tcx > , 
116+     types :  Vec < Span > , 
117+ } 
118+ 
119+ impl  Visitor < ' tcx >  for  TypeParamSpanVisitor < ' tcx >  { 
120+     type  Map  = rustc_middle:: hir:: map:: Map < ' tcx > ; 
121+ 
122+     fn  nested_visit_map ( & mut  self )  -> hir:: intravisit:: NestedVisitorMap < Self :: Map >  { 
123+         hir:: intravisit:: NestedVisitorMap :: OnlyBodies ( self . tcx . hir ( ) ) 
124+     } 
125+ 
126+     fn  visit_ty ( & mut  self ,  arg :  & ' tcx  hir:: Ty < ' tcx > )  { 
127+         match  arg. kind  { 
128+             hir:: TyKind :: Rptr ( _,  ref  mut_ty)  => { 
129+                 // We don't want to suggest looking into borrowing `&T` or `&Self`. 
130+                 hir:: intravisit:: walk_ty ( self ,  mut_ty. ty ) ; 
131+                 return ; 
132+             } 
133+             hir:: TyKind :: Path ( hir:: QPath :: Resolved ( None ,  path) )  => match  & path. segments  { 
134+                 [ segment] 
135+                     if  segment
136+                         . res 
137+                         . map ( |res| match  res { 
138+                             Res :: SelfTy ( _,  _)  | Res :: Def ( hir:: def:: DefKind :: TyParam ,  _)  => true , 
139+                             _ => false , 
140+                         } ) 
141+                         . unwrap_or ( false )  =>
142+                 { 
143+                     self . types . push ( path. span ) ; 
144+                 } 
145+                 _ => { } 
146+             } , 
147+             _ => { } 
148+         } 
149+         hir:: intravisit:: walk_ty ( self ,  arg) ; 
150+     } 
151+ } 
0 commit comments