@@ -178,7 +178,7 @@ fn closure_return_type_suggestion(
178178 ) ;
179179 err. span_label (
180180 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) ,
182182 ) ;
183183}
184184
@@ -220,12 +220,23 @@ impl Into<rustc_errors::DiagnosticId> for TypeAnnotationNeeded {
220220 }
221221}
222222
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+
223232impl < ' 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 (
225236 & self ,
226237 arg : GenericArg < ' tcx > ,
227238 highlight : Option < ty:: print:: RegionHighlightMode > ,
228- ) -> ( String , Option < Span > , Cow < ' static , str > , Option < String > , Option < & ' static str > ) {
239+ ) -> InferDiagnosticsData {
229240 match arg. unpack ( ) {
230241 GenericArgKind :: Type ( ty) => {
231242 if let ty:: Infer ( ty:: TyVar ( ty_vid) ) = * ty. kind ( ) {
@@ -236,32 +247,32 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
236247 var_origin. kind
237248 {
238249 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+ } ;
256267
257268 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 ( ) ,
262273 parent_name,
263- parent_desc ,
264- ) ;
274+ parent_description ,
275+ } ;
265276 }
266277 }
267278 }
@@ -272,56 +283,67 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
272283 printer. region_highlight_mode = highlight;
273284 }
274285 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+ }
276293 }
277294 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 {
279296 let origin =
280297 self . inner . borrow_mut ( ) . const_unification_table ( ) . probe_value ( vid) . origin ;
281298 if let ConstVariableOriginKind :: ConstParameterDefinition ( name, def_id) =
282299 origin. kind
283300 {
284301 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 ( ) ,
307324 parent_name,
308- parent_descr ,
309- ) ;
325+ parent_description ,
326+ } ;
310327 }
311328
312329 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+ }
314344 } else {
315345 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;
322346 }
323- let _ = ct. print ( printer) ;
324- ( s, span, "the constant" . into ( ) , None , None )
325347 }
326348 GenericArgKind :: Lifetime ( _) => bug ! ( "unexpected lifetime" ) ,
327349 }
@@ -331,18 +353,18 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
331353 & self ,
332354 body_id : Option < hir:: BodyId > ,
333355 span : Span ,
334- ty : GenericArg < ' tcx > ,
356+ arg : GenericArg < ' tcx > ,
335357 error_code : TypeAnnotationNeeded ,
336358 ) -> 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 ) ;
339361 let kind_str = match ty. unpack ( ) {
340362 GenericArgKind :: Type ( _) => "type" ,
341363 GenericArgKind :: Const ( _) => "the value" ,
342364 GenericArgKind :: Lifetime ( _) => bug ! ( "unexpected lifetime" ) ,
343365 } ;
344366
345- let mut local_visitor = FindHirNodeVisitor :: new ( & self , ty . into ( ) , span) ;
367+ let mut local_visitor = FindHirNodeVisitor :: new ( & self , arg . into ( ) , span) ;
346368 let ty_to_string = |ty : Ty < ' tcx > | -> String {
347369 let mut s = String :: new ( ) ;
348370 let mut printer = ty:: print:: FmtPrinter :: new ( self . tcx , & mut s, Namespace :: TypeNS ) ;
@@ -372,7 +394,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
372394 }
373395 let err_span = if let Some ( pattern) = local_visitor. found_arg_pattern {
374396 pattern. span
375- } else if let Some ( span) = name_sp {
397+ } else if let Some ( span) = arg_data . span {
376398 // `span` here lets us point at `sum` instead of the entire right hand side expr:
377399 // error[E0282]: type annotations needed
378400 // --> file2.rs:3:15
@@ -419,7 +441,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
419441 _ => String :: new ( ) ,
420442 } ;
421443
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
423445 // trying to infer. In the following example, `ty_msg` contains
424446 // " in `std::result::Result<i32, E>`":
425447 // ```
@@ -458,11 +480,11 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
458480 & mut err,
459481 & decl. output ,
460482 self . tcx . hir ( ) . body ( body_id) ,
461- & descr ,
462- & name,
483+ & arg_data . description ,
484+ & arg_data . name ,
463485 & ret,
464- parent_name,
465- parent_descr ,
486+ arg_data . parent_name ,
487+ arg_data . parent_description ,
466488 ) ;
467489 // We don't want to give the other suggestions when the problem is the
468490 // closure return type.
@@ -476,15 +498,15 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
476498 // nudge them in the right direction.
477499 format ! ( "a boxed closure type like `Box<dyn Fn({}) -> {}>`" , args, ret)
478500 }
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 == "_" => {
480502 let ty = ty_to_string ( ty) ;
481503 format ! ( "the explicit type `{}`, with the type parameters specified" , ty)
482504 }
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 => {
484506 let ty = ty_to_string ( ty) ;
485507 format ! (
486508 "the explicit type `{}`, where the type parameter `{}` is specified" ,
487- ty, name,
509+ ty, arg_data . name,
488510 )
489511 }
490512 _ => "a type" . to_string ( ) ,
@@ -601,7 +623,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
601623 // | ^^^ cannot infer type for `S`
602624 // |
603625 // = 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) ;
605627 if !err
606628 . span
607629 . span_labels ( )
@@ -612,7 +634,13 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
612634 // Avoid multiple labels pointing at `span`.
613635 err. span_label (
614636 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+ ) ,
616644 ) ;
617645 }
618646
@@ -672,7 +700,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
672700 ty : Ty < ' tcx > ,
673701 ) -> DiagnosticBuilder < ' tcx > {
674702 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 ) ;
676704
677705 let mut err = struct_span_err ! (
678706 self . tcx. sess,
@@ -683,12 +711,18 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
683711 ) ;
684712 err. span_label (
685713 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+ ) ,
687721 ) ;
688722 err
689723 }
690724
691- fn missing_type_msg (
725+ fn cannot_infer_msg (
692726 kind_str : & str ,
693727 type_name : & str ,
694728 descr : & str ,
@@ -710,6 +744,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
710744 "" . to_string ( )
711745 } ;
712746
747+ // FIXME: We really shouldn't be dealing with strings here
748+ // but instead use a sensible enum for cases like this.
713749 let preposition = if "the value" == kind_str { "of" } else { "for" } ;
714750 // For example: "cannot infer type for type parameter `T`"
715751 format ! (
0 commit comments