1
1
use crate :: FnCtxt ;
2
2
use rustc_ast:: util:: parser:: PREC_POSTFIX ;
3
- use rustc_data_structures:: fx:: FxHashMap ;
4
3
use rustc_errors:: MultiSpan ;
5
4
use rustc_errors:: { Applicability , Diagnostic , DiagnosticBuilder , ErrorGuaranteed } ;
6
5
use rustc_hir as hir;
7
6
use rustc_hir:: def:: CtorKind ;
8
- use rustc_hir:: intravisit:: Visitor ;
9
7
use rustc_hir:: lang_items:: LangItem ;
10
8
use rustc_hir:: { is_range_literal, Node } ;
11
9
use rustc_infer:: infer:: InferOk ;
12
10
use rustc_middle:: lint:: in_external_macro;
13
11
use rustc_middle:: middle:: stability:: EvalResult ;
14
12
use rustc_middle:: ty:: adjustment:: AllowTwoPhase ;
15
13
use rustc_middle:: ty:: error:: { ExpectedFound , TypeError } ;
16
- use rustc_middle:: ty:: fold:: { BottomUpFolder , TypeFolder } ;
17
- use rustc_middle:: ty:: print:: { with_forced_trimmed_paths, with_no_trimmed_paths} ;
18
- use rustc_middle:: ty:: relate:: TypeRelation ;
19
- use rustc_middle:: ty:: { self , Article , AssocItem , Ty , TypeAndMut , TypeVisitable } ;
14
+ use rustc_middle:: ty:: print:: with_no_trimmed_paths;
15
+ use rustc_middle:: ty:: { self , Article , AssocItem , Ty , TypeAndMut } ;
20
16
use rustc_span:: symbol:: { sym, Symbol } ;
21
17
use rustc_span:: { BytePos , Span } ;
22
18
use rustc_trait_selection:: infer:: InferCtxtExt as _;
23
- use rustc_trait_selection:: traits:: error_reporting:: method_chain:: CollectAllMismatches ;
24
19
use rustc_trait_selection:: traits:: ObligationCause ;
25
20
26
21
use super :: method:: probe;
@@ -45,7 +40,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
45
40
self . annotate_alternative_method_deref ( err, expr, error) ;
46
41
47
42
// Use `||` to give these suggestions a precedence
48
- let suggested = self . suggest_missing_parentheses ( err, expr)
43
+ let _ = self . suggest_missing_parentheses ( err, expr)
49
44
|| self . suggest_remove_last_method_call ( err, expr, expected)
50
45
|| self . suggest_associated_const ( err, expr, expected)
51
46
|| self . suggest_deref_ref_or_into ( err, expr, expected, expr_ty, expected_ty_expr)
@@ -60,9 +55,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
60
55
|| self . suggest_clone_for_ref ( err, expr, expr_ty, expected)
61
56
|| self . suggest_into ( err, expr, expr_ty, expected)
62
57
|| self . suggest_floating_point_literal ( err, expr, expected) ;
63
- if !suggested {
64
- self . point_at_expr_source_of_inferred_type ( err, expr, expr_ty, expected) ;
65
- }
66
58
}
67
59
68
60
pub fn emit_coerce_suggestions (
@@ -216,216 +208,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
216
208
( expected, Some ( err) )
217
209
}
218
210
219
- pub fn point_at_expr_source_of_inferred_type (
220
- & self ,
221
- err : & mut Diagnostic ,
222
- expr : & hir:: Expr < ' _ > ,
223
- found : Ty < ' tcx > ,
224
- expected : Ty < ' tcx > ,
225
- ) -> bool {
226
- let map = self . tcx . hir ( ) ;
227
-
228
- let hir:: ExprKind :: Path ( hir:: QPath :: Resolved ( None , p) ) = expr. kind else { return false ; } ;
229
- let [ hir:: PathSegment { ident, args : None , .. } ] = p. segments else { return false ; } ;
230
- let hir:: def:: Res :: Local ( hir_id) = p. res else { return false ; } ;
231
- let Some ( hir:: Node :: Pat ( pat) ) = map. find ( hir_id) else { return false ; } ;
232
- let Some ( hir:: Node :: Local ( hir:: Local {
233
- ty : None ,
234
- init : Some ( init) ,
235
- ..
236
- } ) ) = map. find_parent ( pat. hir_id ) else { return false ; } ;
237
- let Some ( ty) = self . node_ty_opt ( init. hir_id ) else { return false ; } ;
238
- if ty. is_closure ( ) || init. span . overlaps ( expr. span ) || pat. span . from_expansion ( ) {
239
- return false ;
240
- }
241
-
242
- // Locate all the usages of the relevant binding.
243
- struct FindExprs < ' hir > {
244
- hir_id : hir:: HirId ,
245
- uses : Vec < & ' hir hir:: Expr < ' hir > > ,
246
- }
247
- impl < ' v > Visitor < ' v > for FindExprs < ' v > {
248
- fn visit_expr ( & mut self , ex : & ' v hir:: Expr < ' v > ) {
249
- if let hir:: ExprKind :: Path ( hir:: QPath :: Resolved ( None , path) ) = ex. kind
250
- && let hir:: def:: Res :: Local ( hir_id) = path. res
251
- && hir_id == self . hir_id
252
- {
253
- self . uses . push ( ex) ;
254
- }
255
- hir:: intravisit:: walk_expr ( self , ex) ;
256
- }
257
- }
258
-
259
- let mut expr_finder = FindExprs { hir_id, uses : vec ! [ ] } ;
260
- let id = map. get_parent_item ( hir_id) ;
261
- let hir_id: hir:: HirId = id. into ( ) ;
262
-
263
- let Some ( node) = map. find ( hir_id) else { return false ; } ;
264
- let Some ( body_id) = node. body_id ( ) else { return false ; } ;
265
- let body = map. body ( body_id) ;
266
- expr_finder. visit_expr ( body. value ) ;
267
- // Hack to make equality checks on types with inference variables and regions useful.
268
- let mut eraser = BottomUpFolder {
269
- tcx : self . tcx ,
270
- lt_op : |_| self . tcx . lifetimes . re_erased ,
271
- ct_op : |c| c,
272
- ty_op : |t| match * t. kind ( ) {
273
- ty:: Infer ( ty:: TyVar ( vid) ) => self . tcx . mk_ty_infer ( ty:: TyVar ( self . root_var ( vid) ) ) ,
274
- ty:: Infer ( ty:: IntVar ( _) ) => {
275
- self . tcx . mk_ty_infer ( ty:: IntVar ( ty:: IntVid { index : 0 } ) )
276
- }
277
- ty:: Infer ( ty:: FloatVar ( _) ) => {
278
- self . tcx . mk_ty_infer ( ty:: FloatVar ( ty:: FloatVid { index : 0 } ) )
279
- }
280
- _ => t,
281
- } ,
282
- } ;
283
- let mut prev = eraser. fold_ty ( ty) ;
284
- let mut prev_span = None ;
285
-
286
- for binding in expr_finder. uses {
287
- // In every expression where the binding is referenced, we will look at that
288
- // expression's type and see if it is where the incorrect found type was fully
289
- // "materialized" and point at it. We will also try to provide a suggestion there.
290
- if let Some ( hir:: Node :: Expr ( expr)
291
- | hir:: Node :: Stmt ( hir:: Stmt {
292
- kind : hir:: StmtKind :: Expr ( expr) | hir:: StmtKind :: Semi ( expr) ,
293
- ..
294
- } ) ) = & map. find_parent ( binding. hir_id )
295
- && let hir:: ExprKind :: MethodCall ( segment, rcvr, args, _span) = expr. kind
296
- && rcvr. hir_id == binding. hir_id
297
- && let Some ( def_id) = self . typeck_results . borrow ( ) . type_dependent_def_id ( expr. hir_id )
298
- {
299
- // We special case methods, because they can influence inference through the
300
- // call's arguments and we can provide a more explicit span.
301
- let sig = self . tcx . fn_sig ( def_id) ;
302
- let def_self_ty = sig. input ( 0 ) . skip_binder ( ) ;
303
- let rcvr_ty = self . node_ty ( rcvr. hir_id ) ;
304
- // Get the evaluated type *after* calling the method call, so that the influence
305
- // of the arguments can be reflected in the receiver type. The receiver
306
- // expression has the type *before* theis analysis is done.
307
- let ty = match self . lookup_probe_for_diagnostic (
308
- segment. ident ,
309
- rcvr_ty,
310
- expr,
311
- probe:: ProbeScope :: TraitsInScope ,
312
- None ,
313
- ) {
314
- Ok ( pick) => pick. self_ty ,
315
- Err ( _) => rcvr_ty,
316
- } ;
317
- // Remove one layer of references to account for `&mut self` and
318
- // `&self`, so that we can compare it against the binding.
319
- let ( ty, def_self_ty) = match ( ty. kind ( ) , def_self_ty. kind ( ) ) {
320
- ( ty:: Ref ( _, ty, a) , ty:: Ref ( _, self_ty, b) ) if a == b => ( * ty, * self_ty) ,
321
- _ => ( ty, def_self_ty) ,
322
- } ;
323
- let mut param_args = FxHashMap :: default ( ) ;
324
- let mut param_expected = FxHashMap :: default ( ) ;
325
- let mut param_found = FxHashMap :: default ( ) ;
326
- if self . can_eq ( self . param_env , ty, found) . is_ok ( ) {
327
- // We only point at the first place where the found type was inferred.
328
- for ( i, param_ty) in sig. inputs ( ) . skip_binder ( ) . iter ( ) . skip ( 1 ) . enumerate ( ) {
329
- if def_self_ty. contains ( * param_ty) && let ty:: Param ( _) = param_ty. kind ( ) {
330
- // We found an argument that references a type parameter in `Self`,
331
- // so we assume that this is the argument that caused the found
332
- // type, which we know already because of `can_eq` above was first
333
- // inferred in this method call.
334
- let arg = & args[ i] ;
335
- let arg_ty = self . node_ty ( arg. hir_id ) ;
336
- err. span_label (
337
- arg. span ,
338
- & format ! (
339
- "this is of type `{arg_ty}`, which causes `{ident}` to be \
340
- inferred as `{ty}`",
341
- ) ,
342
- ) ;
343
- param_args. insert ( param_ty, ( arg, arg_ty) ) ;
344
- }
345
- }
346
- }
347
-
348
- // Here we find, for a type param `T`, the type that `T` is in the current
349
- // method call *and* in the original expected type. That way, we can see if we
350
- // can give any structured suggestion for the function argument.
351
- let mut c = CollectAllMismatches {
352
- infcx : & self . infcx ,
353
- param_env : self . param_env ,
354
- errors : vec ! [ ] ,
355
- } ;
356
- let _ = c. relate ( def_self_ty, ty) ;
357
- for error in c. errors {
358
- if let TypeError :: Sorts ( error) = error {
359
- param_found. insert ( error. expected , error. found ) ;
360
- }
361
- }
362
- c. errors = vec ! [ ] ;
363
- let _ = c. relate ( def_self_ty, expected) ;
364
- for error in c. errors {
365
- if let TypeError :: Sorts ( error) = error {
366
- param_expected. insert ( error. expected , error. found ) ;
367
- }
368
- }
369
- for ( param, ( arg, arg_ty) ) in param_args. iter ( ) {
370
- let Some ( expected) = param_expected. get ( param) else { continue ; } ;
371
- let Some ( found) = param_found. get ( param) else { continue ; } ;
372
- if self . can_eq ( self . param_env , * arg_ty, * found) . is_err ( ) { continue ; }
373
- self . emit_coerce_suggestions ( err, arg, * found, * expected, None , None ) ;
374
- }
375
-
376
- let ty = eraser. fold_ty ( ty) ;
377
- if ty. references_error ( ) {
378
- break ;
379
- }
380
- if ty != prev
381
- && param_args. is_empty ( )
382
- && self . can_eq ( self . param_env , ty, found) . is_ok ( )
383
- {
384
- // We only point at the first place where the found type was inferred.
385
- err. span_label (
386
- segment. ident . span ,
387
- with_forced_trimmed_paths ! ( format!(
388
- "here the type of `{ident}` is inferred to be `{ty}`" ,
389
- ) ) ,
390
- ) ;
391
- break ;
392
- } else if !param_args. is_empty ( ) {
393
- break ;
394
- }
395
- prev = ty;
396
- } else {
397
- let ty = eraser. fold_ty ( self . node_ty ( binding. hir_id ) ) ;
398
- if ty. references_error ( ) {
399
- break ;
400
- }
401
- if ty != prev
402
- && let Some ( span) = prev_span
403
- && self . can_eq ( self . param_env , ty, found) . is_ok ( )
404
- {
405
- // We only point at the first place where the found type was inferred.
406
- // We use the *previous* span because if the type is known *here* it means
407
- // it was *evaluated earlier*. We don't do this for method calls because we
408
- // evaluate the method's self type eagerly, but not in any other case.
409
- err. span_label (
410
- span,
411
- with_forced_trimmed_paths ! ( format!(
412
- "here the type of `{ident}` is inferred to be `{ty}`" ,
413
- ) ) ,
414
- ) ;
415
- break ;
416
- }
417
- prev = ty;
418
- }
419
- if binding. hir_id == expr. hir_id {
420
- // Do not look at expressions that come after the expression we were originally
421
- // evaluating and had a type error.
422
- break ;
423
- }
424
- prev_span = Some ( binding. span ) ;
425
- }
426
- true
427
- }
428
-
429
211
fn annotate_expected_due_to_let_ty (
430
212
& self ,
431
213
err : & mut Diagnostic ,
0 commit comments