@@ -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,80 @@ 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+ if let hir:: ExprKind :: Path ( hir:: QPath :: Resolved (
183+ None ,
184+ hir:: Path { res : hir:: def:: Res :: Local ( hir_id) , .. } ,
185+ ) ) = lhs. kind
186+ {
187+ if let Some ( hir:: Node :: Binding ( pat) ) = self . tcx . hir ( ) . find ( * hir_id) {
188+ let parent = self . tcx . hir ( ) . get_parent_node ( pat. hir_id ) ;
189+ primary_span = pat. span ;
190+ secondary_span = pat. span ;
191+ match self . tcx . hir ( ) . find ( parent) {
192+ Some ( hir:: Node :: Local ( hir:: Local { ty : Some ( ty) , .. } ) ) => {
193+ primary_span = ty. span ;
194+ post_message = " type" ;
195+ }
196+ Some ( hir:: Node :: Local ( hir:: Local { init : Some ( init) , .. } ) ) => {
197+ primary_span = init. span ;
198+ post_message = " value" ;
199+ }
200+ Some ( hir:: Node :: Param ( hir:: Param { ty_span, .. } ) ) => {
201+ primary_span = * ty_span;
202+ post_message = " parameter type" ;
203+ }
204+ _ => { }
205+ }
206+ }
207+ }
208+
209+ if primary_span != secondary_span
210+ && self
211+ . tcx
212+ . sess
213+ . source_map ( )
214+ . is_multiline ( secondary_span. shrink_to_hi ( ) . until ( primary_span) )
215+ {
216+ // We are pointing at the binding's type or initializer value, but it's pattern
217+ // is in a different line, so we point at both.
218+ err. span_label ( secondary_span, "expected due to the type of this binding" ) ;
219+ err. span_label ( primary_span, & format ! ( "expected due to this{}" , post_message) ) ;
220+ } else if post_message == "" {
221+ // We are pointing at either the assignment lhs or the binding def pattern.
222+ err. span_label ( primary_span, "expected due to the type of this binding" ) ;
223+ } else {
224+ // We are pointing at the binding's type or initializer value.
225+ err. span_label ( primary_span, & format ! ( "expected due to this{}" , post_message) ) ;
226+ }
227+
228+ if !lhs. is_syntactic_place_expr ( ) {
229+ // We already emitted E0070 "invalid left-hand side of assignment", so we
230+ // silence this.
231+ err. delay_as_bug ( ) ;
232+ }
233+ }
234+ _ => { }
168235 }
169236 }
170237
0 commit comments