@@ -178,7 +178,7 @@ fn closure_return_type_suggestion(
178
178
) ;
179
179
err. span_label (
180
180
span,
181
- InferCtxt :: missing_type_msg ( "type" , & name, & descr, parent_name, parent_descr) ,
181
+ InferCtxt :: cannot_infer_msg ( "type" , & name, & descr, parent_name, parent_descr) ,
182
182
) ;
183
183
}
184
184
@@ -220,12 +220,23 @@ impl Into<rustc_errors::DiagnosticId> for TypeAnnotationNeeded {
220
220
}
221
221
}
222
222
223
+ /// Information about a constant or a type containing inference variables.
224
+ pub struct InferDiagnosticsData {
225
+ pub name : String ,
226
+ pub span : Option < Span > ,
227
+ pub description : Cow < ' static , str > ,
228
+ pub parent_name : Option < String > ,
229
+ pub parent_description : Option < & ' static str > ,
230
+ }
231
+
223
232
impl < ' a , ' tcx > InferCtxt < ' a , ' tcx > {
224
- pub fn extract_type_name (
233
+ /// Extracts data used by diagnostic for either types or constants
234
+ /// which were stuck during inference.
235
+ pub fn extract_infer_data (
225
236
& self ,
226
237
arg : GenericArg < ' tcx > ,
227
238
highlight : Option < ty:: print:: RegionHighlightMode > ,
228
- ) -> ( String , Option < Span > , Cow < ' static , str > , Option < String > , Option < & ' static str > ) {
239
+ ) -> InferDiagnosticsData {
229
240
match arg. unpack ( ) {
230
241
GenericArgKind :: Type ( ty) => {
231
242
if let ty:: Infer ( ty:: TyVar ( ty_vid) ) = * ty. kind ( ) {
@@ -236,32 +247,32 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
236
247
var_origin. kind
237
248
{
238
249
let parent_def_id = def_id. and_then ( |def_id| self . tcx . parent ( def_id) ) ;
239
- let ( parent_name, parent_desc ) = if let Some ( parent_def_id ) = parent_def_id
240
- {
241
- let parent_name = self
242
- . tcx
243
- . def_key ( parent_def_id)
244
- . disambiguated_data
245
- . data
246
- . get_opt_name ( )
247
- . map ( |parent_symbol| parent_symbol. to_string ( ) ) ;
248
-
249
- (
250
- parent_name,
251
- Some ( self . tcx . def_kind ( parent_def_id) . descr ( parent_def_id) ) ,
252
- )
253
- } else {
254
- ( None , None )
255
- } ;
250
+ let ( parent_name, parent_description ) =
251
+ if let Some ( parent_def_id ) = parent_def_id {
252
+ let parent_name = self
253
+ . tcx
254
+ . def_key ( parent_def_id)
255
+ . disambiguated_data
256
+ . data
257
+ . get_opt_name ( )
258
+ . map ( |parent_symbol| parent_symbol. to_string ( ) ) ;
259
+
260
+ (
261
+ parent_name,
262
+ Some ( self . tcx . def_kind ( parent_def_id) . descr ( parent_def_id) ) ,
263
+ )
264
+ } else {
265
+ ( None , None )
266
+ } ;
256
267
257
268
if name != kw:: SelfUpper {
258
- return (
259
- name. to_string ( ) ,
260
- Some ( var_origin. span ) ,
261
- "type parameter" . into ( ) ,
269
+ return InferDiagnosticsData {
270
+ name : name . to_string ( ) ,
271
+ span : Some ( var_origin. span ) ,
272
+ description : "type parameter" . into ( ) ,
262
273
parent_name,
263
- parent_desc ,
264
- ) ;
274
+ parent_description ,
275
+ } ;
265
276
}
266
277
}
267
278
}
@@ -272,56 +283,67 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
272
283
printer. region_highlight_mode = highlight;
273
284
}
274
285
let _ = ty. print ( printer) ;
275
- ( s, None , ty. prefix_string ( ) , None , None )
286
+ InferDiagnosticsData {
287
+ name : s,
288
+ span : None ,
289
+ description : ty. prefix_string ( ) ,
290
+ parent_name : None ,
291
+ parent_description : None ,
292
+ }
276
293
}
277
294
GenericArgKind :: Const ( ct) => {
278
- let span = if let ty:: ConstKind :: Infer ( InferConst :: Var ( vid) ) = ct. val {
295
+ if let ty:: ConstKind :: Infer ( InferConst :: Var ( vid) ) = ct. val {
279
296
let origin =
280
297
self . inner . borrow_mut ( ) . const_unification_table ( ) . probe_value ( vid) . origin ;
281
298
if let ConstVariableOriginKind :: ConstParameterDefinition ( name, def_id) =
282
299
origin. kind
283
300
{
284
301
let parent_def_id = self . tcx . parent ( def_id) ;
285
- let ( parent_name, parent_descr ) = if let Some ( parent_def_id ) = parent_def_id
286
- {
287
- let parent_name = self
288
- . tcx
289
- . def_key ( parent_def_id)
290
- . disambiguated_data
291
- . data
292
- . get_opt_name ( )
293
- . map ( |parent_symbol| parent_symbol. to_string ( ) ) ;
294
-
295
- (
296
- parent_name,
297
- Some ( self . tcx . def_kind ( parent_def_id) . descr ( parent_def_id) ) ,
298
- )
299
- } else {
300
- ( None , None )
301
- } ;
302
-
303
- return (
304
- name. to_string ( ) ,
305
- Some ( origin. span ) ,
306
- "const parameter" . into ( ) ,
302
+ let ( parent_name, parent_description ) =
303
+ if let Some ( parent_def_id ) = parent_def_id {
304
+ let parent_name = self
305
+ . tcx
306
+ . def_key ( parent_def_id)
307
+ . disambiguated_data
308
+ . data
309
+ . get_opt_name ( )
310
+ . map ( |parent_symbol| parent_symbol. to_string ( ) ) ;
311
+
312
+ (
313
+ parent_name,
314
+ Some ( self . tcx . def_kind ( parent_def_id) . descr ( parent_def_id) ) ,
315
+ )
316
+ } else {
317
+ ( None , None )
318
+ } ;
319
+
320
+ return InferDiagnosticsData {
321
+ name : name . to_string ( ) ,
322
+ span : Some ( origin. span ) ,
323
+ description : "const parameter" . into ( ) ,
307
324
parent_name,
308
- parent_descr ,
309
- ) ;
325
+ parent_description ,
326
+ } ;
310
327
}
311
328
312
329
debug_assert ! ( !origin. span. is_dummy( ) ) ;
313
- Some ( origin. span )
330
+ let mut s = String :: new ( ) ;
331
+ let mut printer =
332
+ ty:: print:: FmtPrinter :: new ( self . tcx , & mut s, Namespace :: ValueNS ) ;
333
+ if let Some ( highlight) = highlight {
334
+ printer. region_highlight_mode = highlight;
335
+ }
336
+ let _ = ct. print ( printer) ;
337
+ InferDiagnosticsData {
338
+ name : s,
339
+ span : Some ( origin. span ) ,
340
+ description : "the constant" . into ( ) ,
341
+ parent_name : None ,
342
+ parent_description : None ,
343
+ }
314
344
} else {
315
345
bug ! ( "unexpect const: {:?}" , ct) ;
316
- } ;
317
-
318
- let mut s = String :: new ( ) ;
319
- let mut printer = ty:: print:: FmtPrinter :: new ( self . tcx , & mut s, Namespace :: ValueNS ) ;
320
- if let Some ( highlight) = highlight {
321
- printer. region_highlight_mode = highlight;
322
346
}
323
- let _ = ct. print ( printer) ;
324
- ( s, span, "the constant" . into ( ) , None , None )
325
347
}
326
348
GenericArgKind :: Lifetime ( _) => bug ! ( "unexpected lifetime" ) ,
327
349
}
@@ -331,18 +353,18 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
331
353
& self ,
332
354
body_id : Option < hir:: BodyId > ,
333
355
span : Span ,
334
- ty : GenericArg < ' tcx > ,
356
+ arg : GenericArg < ' tcx > ,
335
357
error_code : TypeAnnotationNeeded ,
336
358
) -> DiagnosticBuilder < ' tcx > {
337
- let ty = self . resolve_vars_if_possible ( & ty ) ;
338
- let ( name , name_sp , descr , parent_name , parent_descr ) = self . extract_type_name ( ty , None ) ;
359
+ let ty = self . resolve_vars_if_possible ( & arg ) ;
360
+ let arg_data = self . extract_infer_data ( arg , None ) ;
339
361
let kind_str = match ty. unpack ( ) {
340
362
GenericArgKind :: Type ( _) => "type" ,
341
363
GenericArgKind :: Const ( _) => "the value" ,
342
364
GenericArgKind :: Lifetime ( _) => bug ! ( "unexpected lifetime" ) ,
343
365
} ;
344
366
345
- let mut local_visitor = FindHirNodeVisitor :: new ( & self , ty . into ( ) , span) ;
367
+ let mut local_visitor = FindHirNodeVisitor :: new ( & self , arg . into ( ) , span) ;
346
368
let ty_to_string = |ty : Ty < ' tcx > | -> String {
347
369
let mut s = String :: new ( ) ;
348
370
let mut printer = ty:: print:: FmtPrinter :: new ( self . tcx , & mut s, Namespace :: TypeNS ) ;
@@ -372,7 +394,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
372
394
}
373
395
let err_span = if let Some ( pattern) = local_visitor. found_arg_pattern {
374
396
pattern. span
375
- } else if let Some ( span) = name_sp {
397
+ } else if let Some ( span) = arg_data . span {
376
398
// `span` here lets us point at `sum` instead of the entire right hand side expr:
377
399
// error[E0282]: type annotations needed
378
400
// --> file2.rs:3:15
@@ -419,7 +441,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
419
441
_ => String :: new ( ) ,
420
442
} ;
421
443
422
- // When `name` corresponds to a type argument, show the path of the full type we're
444
+ // When `arg_data. name` corresponds to a type argument, show the path of the full type we're
423
445
// trying to infer. In the following example, `ty_msg` contains
424
446
// " in `std::result::Result<i32, E>`":
425
447
// ```
@@ -458,11 +480,11 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
458
480
& mut err,
459
481
& decl. output ,
460
482
self . tcx . hir ( ) . body ( body_id) ,
461
- & descr ,
462
- & name,
483
+ & arg_data . description ,
484
+ & arg_data . name ,
463
485
& ret,
464
- parent_name,
465
- parent_descr ,
486
+ arg_data . parent_name ,
487
+ arg_data . parent_description ,
466
488
) ;
467
489
// We don't want to give the other suggestions when the problem is the
468
490
// closure return type.
@@ -476,15 +498,15 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
476
498
// nudge them in the right direction.
477
499
format ! ( "a boxed closure type like `Box<dyn Fn({}) -> {}>`" , args, ret)
478
500
}
479
- Some ( ty) if is_named_and_not_impl_trait ( ty) && name == "_" => {
501
+ Some ( ty) if is_named_and_not_impl_trait ( ty) && arg_data . name == "_" => {
480
502
let ty = ty_to_string ( ty) ;
481
503
format ! ( "the explicit type `{}`, with the type parameters specified" , ty)
482
504
}
483
- Some ( ty) if is_named_and_not_impl_trait ( ty) && ty. to_string ( ) != name => {
505
+ Some ( ty) if is_named_and_not_impl_trait ( ty) && ty. to_string ( ) != arg_data . name => {
484
506
let ty = ty_to_string ( ty) ;
485
507
format ! (
486
508
"the explicit type `{}`, where the type parameter `{}` is specified" ,
487
- ty, name,
509
+ ty, arg_data . name,
488
510
)
489
511
}
490
512
_ => "a type" . to_string ( ) ,
@@ -601,7 +623,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
601
623
// | ^^^ cannot infer type for `S`
602
624
// |
603
625
// = note: type must be known at this point
604
- let span = name_sp . unwrap_or ( err_span) ;
626
+ let span = arg_data . span . unwrap_or ( err_span) ;
605
627
if !err
606
628
. span
607
629
. span_labels ( )
@@ -612,7 +634,13 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
612
634
// Avoid multiple labels pointing at `span`.
613
635
err. span_label (
614
636
span,
615
- InferCtxt :: missing_type_msg ( kind_str, & name, & descr, parent_name, parent_descr) ,
637
+ InferCtxt :: cannot_infer_msg (
638
+ kind_str,
639
+ & arg_data. name ,
640
+ & arg_data. description ,
641
+ arg_data. parent_name ,
642
+ arg_data. parent_description ,
643
+ ) ,
616
644
) ;
617
645
}
618
646
@@ -672,7 +700,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
672
700
ty : Ty < ' tcx > ,
673
701
) -> DiagnosticBuilder < ' tcx > {
674
702
let ty = self . resolve_vars_if_possible ( & ty) ;
675
- let ( name , _ , descr , parent_name , parent_descr ) = self . extract_type_name ( ty. into ( ) , None ) ;
703
+ let data = self . extract_infer_data ( ty. into ( ) , None ) ;
676
704
677
705
let mut err = struct_span_err ! (
678
706
self . tcx. sess,
@@ -683,12 +711,18 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
683
711
) ;
684
712
err. span_label (
685
713
span,
686
- InferCtxt :: missing_type_msg ( "type" , & name, & descr, parent_name, parent_descr) ,
714
+ InferCtxt :: cannot_infer_msg (
715
+ "type" ,
716
+ & data. name ,
717
+ & data. description ,
718
+ data. parent_name ,
719
+ data. parent_description ,
720
+ ) ,
687
721
) ;
688
722
err
689
723
}
690
724
691
- fn missing_type_msg (
725
+ fn cannot_infer_msg (
692
726
kind_str : & str ,
693
727
type_name : & str ,
694
728
descr : & str ,
@@ -710,6 +744,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
710
744
"" . to_string ( )
711
745
} ;
712
746
747
+ // FIXME: We really shouldn't be dealing with strings here
748
+ // but instead use a sensible enum for cases like this.
713
749
let preposition = if "the value" == kind_str { "of" } else { "for" } ;
714
750
// For example: "cannot infer type for type parameter `T`"
715
751
format ! (
0 commit comments