@@ -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,80 @@ 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
+ 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
+ _ => { }
168
235
}
169
236
}
170
237
0 commit comments