@@ -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