@@ -10,6 +10,7 @@ use rustc_hir::lang_items::LangItem;
1010use  rustc_hir:: { is_range_literal,  Node } ; 
1111use  rustc_middle:: lint:: in_external_macro; 
1212use  rustc_middle:: ty:: adjustment:: AllowTwoPhase ; 
13+ use  rustc_middle:: ty:: error:: { ExpectedFound ,  TypeError } ; 
1314use  rustc_middle:: ty:: print:: with_no_trimmed_paths; 
1415use  rustc_middle:: ty:: { self ,  AssocItem ,  Ty ,  TypeAndMut } ; 
1516use  rustc_span:: symbol:: sym; 
@@ -27,8 +28,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
2728        expr_ty :  Ty < ' tcx > , 
2829        expected :  Ty < ' tcx > , 
2930        expected_ty_expr :  Option < & ' tcx  hir:: Expr < ' tcx > > , 
31+         error :  TypeError < ' tcx > , 
3032    )  { 
31-         self . annotate_expected_due_to_let_ty ( err,  expr) ; 
33+         self . annotate_expected_due_to_let_ty ( err,  expr,  error ) ; 
3234        self . suggest_box_deref ( err,  expr,  expected,  expr_ty) ; 
3335        self . suggest_compatible_variants ( err,  expr,  expected,  expr_ty) ; 
3436        self . suggest_deref_ref_or_into ( err,  expr,  expected,  expr_ty,  expected_ty_expr) ; 
@@ -145,9 +147,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
145147        let  expr = expr. peel_drop_temps ( ) ; 
146148        let  cause = self . misc ( expr. span ) ; 
147149        let  expr_ty = self . resolve_vars_with_obligations ( checked_ty) ; 
148-         let  mut  err = self . report_mismatched_types ( & cause,  expected,  expr_ty,  e) ; 
150+         let  mut  err = self . report_mismatched_types ( & cause,  expected,  expr_ty,  e. clone ( ) ) ; 
149151
150-         self . emit_coerce_suggestions ( & mut  err,  expr,  expr_ty,  expected,  expected_ty_expr) ; 
152+         self . emit_coerce_suggestions ( & mut  err,  expr,  expr_ty,  expected,  expected_ty_expr,  e ) ; 
151153
152154        ( expected,  Some ( err) ) 
153155    } 
@@ -156,15 +158,104 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
156158        & self , 
157159        err :  & mut  DiagnosticBuilder < ' _ > , 
158160        expr :  & hir:: Expr < ' _ > , 
161+         error :  TypeError < ' _ > , 
159162    )  { 
160163        let  parent = self . tcx . hir ( ) . get_parent_node ( expr. hir_id ) ; 
161-         if   let   Some ( hir:: Node :: Local ( hir :: Local   {   ty :   Some ( ty ) ,   init :   Some ( init ) ,  ..  } ) )  = 
162-             self . tcx . hir ( ) . find ( parent ) 
163-         { 
164-             if  init . hir_id  == expr . hir_id   { 
164+         match   ( self . tcx . hir ( ) . find ( parent ) ,  error )   { 
165+             ( Some ( hir:: Node :: Local ( hir :: Local   {   ty :   Some ( ty ) ,   init :   Some ( init ) ,  ..  } ) ) ,  _ ) 
166+                  if  init . hir_id  == expr . hir_id  => 
167+             { 
165168                // Point at `let` assignment type. 
166169                err. span_label ( ty. span ,  "expected due to this" ) ; 
167170            } 
171+             ( 
172+                 Some ( hir:: Node :: Expr ( hir:: Expr  { 
173+                     kind :  hir:: ExprKind :: Assign ( lhs,  rhs,  _) ,  ..
174+                 } ) ) , 
175+                 TypeError :: Sorts ( ExpectedFound  {  expected,  .. } ) , 
176+             )  if  rhs. hir_id  == expr. hir_id  && !expected. is_closure ( )  => { 
177+                 // We ignore closures explicitly because we already point at them elsewhere. 
178+                 // Point at the assigned-to binding. 
179+                 let  mut  primary_span = lhs. span ; 
180+                 let  mut  secondary_span = lhs. span ; 
181+                 let  mut  post_message = "" ; 
182+                 match  lhs. kind  { 
183+                     hir:: ExprKind :: Path ( hir:: QPath :: Resolved ( 
184+                         None , 
185+                         hir:: Path  { 
186+                             res : 
187+                                 hir:: def:: Res :: Def ( 
188+                                     hir:: def:: DefKind :: Static  | hir:: def:: DefKind :: Const , 
189+                                     def_id, 
190+                                 ) , 
191+                             ..
192+                         } , 
193+                     ) )  => { 
194+                         if  let  Some ( hir:: Node :: Item ( hir:: Item  { 
195+                             ident, 
196+                             kind :  hir:: ItemKind :: Static ( ty,  ..)  | hir:: ItemKind :: Const ( ty,  ..) , 
197+                             ..
198+                         } ) )  = self . tcx . hir ( ) . get_if_local ( * def_id) 
199+                         { 
200+                             primary_span = ty. span ; 
201+                             secondary_span = ident. span ; 
202+                             post_message = " type" ; 
203+                         } 
204+                     } 
205+                     hir:: ExprKind :: Path ( hir:: QPath :: Resolved ( 
206+                         None , 
207+                         hir:: Path  {  res :  hir:: def:: Res :: Local ( hir_id) ,  .. } , 
208+                     ) )  => { 
209+                         if  let  Some ( hir:: Node :: Binding ( pat) )  = self . tcx . hir ( ) . find ( * hir_id)  { 
210+                             let  parent = self . tcx . hir ( ) . get_parent_node ( pat. hir_id ) ; 
211+                             primary_span = pat. span ; 
212+                             secondary_span = pat. span ; 
213+                             match  self . tcx . hir ( ) . find ( parent)  { 
214+                                 Some ( hir:: Node :: Local ( hir:: Local  {  ty :  Some ( ty) ,  .. } ) )  => { 
215+                                     primary_span = ty. span ; 
216+                                     post_message = " type" ; 
217+                                 } 
218+                                 Some ( hir:: Node :: Local ( hir:: Local  {  init :  Some ( init) ,  .. } ) )  => { 
219+                                     primary_span = init. span ; 
220+                                     post_message = " value" ; 
221+                                 } 
222+                                 Some ( hir:: Node :: Param ( hir:: Param  {  ty_span,  .. } ) )  => { 
223+                                     primary_span = * ty_span; 
224+                                     post_message = " parameter type" ; 
225+                                 } 
226+                                 _ => { } 
227+                             } 
228+                         } 
229+                     } 
230+                     _ => { } 
231+                 } 
232+ 
233+                 if  primary_span != secondary_span
234+                     && self 
235+                         . tcx 
236+                         . sess 
237+                         . source_map ( ) 
238+                         . is_multiline ( secondary_span. shrink_to_hi ( ) . until ( primary_span) ) 
239+                 { 
240+                     // We are pointing at the binding's type or initializer value, but it's pattern 
241+                     // is in a different line, so we point at both. 
242+                     err. span_label ( secondary_span,  "expected due to the type of this binding" ) ; 
243+                     err. span_label ( primary_span,  & format ! ( "expected due to this{}" ,  post_message) ) ; 
244+                 }  else  if  post_message == ""  { 
245+                     // We are pointing at either the assignment lhs or the binding def pattern. 
246+                     err. span_label ( primary_span,  "expected due to the type of this binding" ) ; 
247+                 }  else  { 
248+                     // We are pointing at the binding's type or initializer value. 
249+                     err. span_label ( primary_span,  & format ! ( "expected due to this{}" ,  post_message) ) ; 
250+                 } 
251+ 
252+                 if  !lhs. is_syntactic_place_expr ( )  { 
253+                     // We already emitted E0070 "invalid left-hand side of assignment", so we 
254+                     // silence this. 
255+                     err. delay_as_bug ( ) ; 
256+                 } 
257+             } 
258+             _ => { } 
168259        } 
169260    } 
170261
0 commit comments