@@ -10,6 +10,7 @@ use rustc_hir::lang_items::LangItem;
10
10
use rustc_hir:: { is_range_literal, Node } ;
11
11
use rustc_middle:: lint:: in_external_macro;
12
12
use rustc_middle:: ty:: adjustment:: AllowTwoPhase ;
13
+ use rustc_middle:: ty:: error:: { ExpectedFound , TypeError } ;
13
14
use rustc_middle:: ty:: print:: with_no_trimmed_paths;
14
15
use rustc_middle:: ty:: { self , AssocItem , Ty , TypeAndMut } ;
15
16
use rustc_span:: symbol:: sym;
@@ -27,8 +28,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
27
28
expr_ty : Ty < ' tcx > ,
28
29
expected : Ty < ' tcx > ,
29
30
expected_ty_expr : Option < & ' tcx hir:: Expr < ' tcx > > ,
31
+ error : TypeError < ' tcx > ,
30
32
) {
31
- self . annotate_expected_due_to_let_ty ( err, expr) ;
33
+ self . annotate_expected_due_to_let_ty ( err, expr, error ) ;
32
34
self . suggest_box_deref ( err, expr, expected, expr_ty) ;
33
35
self . suggest_compatible_variants ( err, expr, expected, expr_ty) ;
34
36
self . suggest_deref_ref_or_into ( err, expr, expected, expr_ty, expected_ty_expr) ;
@@ -145,9 +147,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
145
147
let expr = expr. peel_drop_temps ( ) ;
146
148
let cause = self . misc ( expr. span ) ;
147
149
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 ( ) ) ;
149
151
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 ) ;
151
153
152
154
( expected, Some ( err) )
153
155
}
@@ -156,15 +158,104 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
156
158
& self ,
157
159
err : & mut DiagnosticBuilder < ' _ > ,
158
160
expr : & hir:: Expr < ' _ > ,
161
+ error : TypeError < ' _ > ,
159
162
) {
160
163
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
+ {
165
168
// Point at `let` assignment type.
166
169
err. span_label ( ty. span , "expected due to this" ) ;
167
170
}
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
+ _ => { }
168
259
}
169
260
}
170
261
0 commit comments