@@ -20,7 +20,7 @@ use rustc_middle::ty::print::{FmtPrinter, PrettyPrinter, Print, Printer};
2020use  rustc_middle:: ty:: { self ,  DefIdTree ,  InferConst } ; 
2121use  rustc_middle:: ty:: { GenericArg ,  GenericArgKind ,  SubstsRef } ; 
2222use  rustc_middle:: ty:: { IsSuggestable ,  Ty ,  TyCtxt ,  TypeckResults } ; 
23- use  rustc_span:: symbol:: { kw,  Ident } ; 
23+ use  rustc_span:: symbol:: { kw,  sym ,   Ident } ; 
2424use  rustc_span:: { BytePos ,  Span } ; 
2525use  std:: borrow:: Cow ; 
2626use  std:: iter; 
@@ -79,7 +79,7 @@ impl InferenceDiagnosticsData {
7979
8080    fn  where_x_is_kind ( & self ,  in_type :  Ty < ' _ > )  -> & ' static  str  { 
8181        if  in_type. is_ty_infer ( )  { 
82-             "empty " 
82+             "" 
8383        }  else  if  self . name  == "_"  { 
8484            // FIXME: Consider specializing this message if there is a single `_` 
8585            // in the type. 
@@ -183,13 +183,24 @@ fn fmt_printer<'a, 'tcx>(infcx: &'a InferCtxt<'tcx>, ns: Namespace) -> FmtPrinte
183183    printer
184184} 
185185
186- fn  ty_to_string < ' tcx > ( infcx :  & InferCtxt < ' tcx > ,  ty :  Ty < ' tcx > )  -> String  { 
186+ fn  ty_to_string < ' tcx > ( 
187+     infcx :  & InferCtxt < ' tcx > , 
188+     ty :  Ty < ' tcx > , 
189+     called_method_def_id :  Option < DefId > , 
190+ )  -> String  { 
187191    let  printer = fmt_printer ( infcx,  Namespace :: TypeNS ) ; 
188192    let  ty = infcx. resolve_vars_if_possible ( ty) ; 
189-     match  ty. kind ( )  { 
193+     match  ( ty. kind ( ) ,  called_method_def_id )  { 
190194        // We don't want the regular output for `fn`s because it includes its path in 
191195        // invalid pseudo-syntax, we want the `fn`-pointer output instead. 
192-         ty:: FnDef ( ..)  => ty. fn_sig ( infcx. tcx ) . print ( printer) . unwrap ( ) . into_buffer ( ) , 
196+         ( ty:: FnDef ( ..) ,  _)  => ty. fn_sig ( infcx. tcx ) . print ( printer) . unwrap ( ) . into_buffer ( ) , 
197+         ( _,  Some ( def_id) ) 
198+             if  ty. is_ty_infer ( ) 
199+                 && infcx. tcx . get_diagnostic_item ( sym:: iterator_collect_fn)  == Some ( def_id)  =>
200+         { 
201+             "Vec<_>" . to_string ( ) 
202+         } 
203+         _ if  ty. is_ty_infer ( )  => "/* Type */" . to_string ( ) , 
193204        // FIXME: The same thing for closures, but this only works when the closure 
194205        // does not capture anything. 
195206        // 
@@ -213,15 +224,15 @@ fn closure_as_fn_str<'tcx>(infcx: &InferCtxt<'tcx>, ty: Ty<'tcx>) -> String {
213224        . map ( |args| { 
214225            args. tuple_fields ( ) 
215226                . iter ( ) 
216-                 . map ( |arg| ty_to_string ( infcx,  arg) ) 
227+                 . map ( |arg| ty_to_string ( infcx,  arg,   None ) ) 
217228                . collect :: < Vec < _ > > ( ) 
218229                . join ( ", " ) 
219230        } ) 
220231        . unwrap_or_default ( ) ; 
221232    let  ret = if  fn_sig. output ( ) . skip_binder ( ) . is_unit ( )  { 
222233        String :: new ( ) 
223234    }  else  { 
224-         format ! ( " -> {}" ,  ty_to_string( infcx,  fn_sig. output( ) . skip_binder( ) ) ) 
235+         format ! ( " -> {}" ,  ty_to_string( infcx,  fn_sig. output( ) . skip_binder( ) ,   None ) ) 
225236    } ; 
226237    format ! ( "fn({}){}" ,  args,  ret) 
227238} 
@@ -368,6 +379,7 @@ impl<'tcx> InferCtxt<'tcx> {
368379} 
369380
370381impl < ' tcx >  TypeErrCtxt < ' _ ,  ' tcx >  { 
382+     #[ instrument( level = "debug" ,  skip( self ,  error_code) ) ]  
371383    pub  fn  emit_inference_failure_err ( 
372384        & self , 
373385        body_id :  Option < hir:: BodyId > , 
@@ -406,7 +418,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
406418        let  mut  infer_subdiags = Vec :: new ( ) ; 
407419        let  mut  multi_suggestions = Vec :: new ( ) ; 
408420        match  kind { 
409-             InferSourceKind :: LetBinding  {  insert_span,  pattern_name,  ty }  => { 
421+             InferSourceKind :: LetBinding  {  insert_span,  pattern_name,  ty,  def_id  }  => { 
410422                infer_subdiags. push ( SourceKindSubdiag :: LetLike  { 
411423                    span :  insert_span, 
412424                    name :  pattern_name. map ( |name| name. to_string ( ) ) . unwrap_or_else ( String :: new) , 
@@ -415,7 +427,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
415427                    prefix :  arg_data. kind . try_get_prefix ( ) . unwrap_or_default ( ) , 
416428                    arg_name :  arg_data. name , 
417429                    kind :  if  pattern_name. is_some ( )  {  "with_pattern"  }  else  {  "other"  } , 
418-                     type_name :  ty_to_string ( self ,  ty) , 
430+                     type_name :  ty_to_string ( self ,  ty,  def_id ) , 
419431                } ) ; 
420432            } 
421433            InferSourceKind :: ClosureArg  {  insert_span,  ty }  => { 
@@ -427,7 +439,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
427439                    prefix :  arg_data. kind . try_get_prefix ( ) . unwrap_or_default ( ) , 
428440                    arg_name :  arg_data. name , 
429441                    kind :  "closure" , 
430-                     type_name :  ty_to_string ( self ,  ty) , 
442+                     type_name :  ty_to_string ( self ,  ty,   None ) , 
431443                } ) ; 
432444            } 
433445            InferSourceKind :: GenericArg  { 
@@ -456,33 +468,39 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
456468                    parent_name, 
457469                } ) ; 
458470
459-                 let  args = fmt_printer ( self ,  Namespace :: TypeNS ) 
460-                     . comma_sep ( generic_args. iter ( ) . copied ( ) . map ( |arg| { 
461-                         if  arg. is_suggestable ( self . tcx ,  true )  { 
462-                             return  arg; 
463-                         } 
471+                 let  args = if  self . infcx . tcx . get_diagnostic_item ( sym:: iterator_collect_fn) 
472+                     == Some ( generics_def_id) 
473+                 { 
474+                     "Vec<_>" . to_string ( ) 
475+                 }  else  { 
476+                     fmt_printer ( self ,  Namespace :: TypeNS ) 
477+                         . comma_sep ( generic_args. iter ( ) . copied ( ) . map ( |arg| { 
478+                             if  arg. is_suggestable ( self . tcx ,  true )  { 
479+                                 return  arg; 
480+                             } 
464481
465-                         match  arg. unpack ( )  { 
466-                             GenericArgKind :: Lifetime ( _)  => bug ! ( "unexpected lifetime" ) , 
467-                             GenericArgKind :: Type ( _)  => self 
468-                                 . next_ty_var ( TypeVariableOrigin  { 
469-                                     span :  rustc_span:: DUMMY_SP , 
470-                                     kind :  TypeVariableOriginKind :: MiscVariable , 
471-                                 } ) 
472-                                 . into ( ) , 
473-                             GenericArgKind :: Const ( arg)  => self 
474-                                 . next_const_var ( 
475-                                     arg. ty ( ) , 
476-                                     ConstVariableOrigin  { 
482+                             match  arg. unpack ( )  { 
483+                                 GenericArgKind :: Lifetime ( _)  => bug ! ( "unexpected lifetime" ) , 
484+                                 GenericArgKind :: Type ( _)  => self 
485+                                     . next_ty_var ( TypeVariableOrigin  { 
477486                                        span :  rustc_span:: DUMMY_SP , 
478-                                         kind :  ConstVariableOriginKind :: MiscVariable , 
479-                                     } , 
480-                                 ) 
481-                                 . into ( ) , 
482-                         } 
483-                     } ) ) 
484-                     . unwrap ( ) 
485-                     . into_buffer ( ) ; 
487+                                         kind :  TypeVariableOriginKind :: MiscVariable , 
488+                                     } ) 
489+                                     . into ( ) , 
490+                                 GenericArgKind :: Const ( arg)  => self 
491+                                     . next_const_var ( 
492+                                         arg. ty ( ) , 
493+                                         ConstVariableOrigin  { 
494+                                             span :  rustc_span:: DUMMY_SP , 
495+                                             kind :  ConstVariableOriginKind :: MiscVariable , 
496+                                         } , 
497+                                     ) 
498+                                     . into ( ) , 
499+                             } 
500+                         } ) ) 
501+                         . unwrap ( ) 
502+                         . into_buffer ( ) 
503+                 } ; 
486504
487505                if  !have_turbofish { 
488506                    infer_subdiags. push ( SourceKindSubdiag :: GenericSuggestion  { 
@@ -520,7 +538,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
520538                ) ) ; 
521539            } 
522540            InferSourceKind :: ClosureReturn  {  ty,  data,  should_wrap_expr }  => { 
523-                 let  ty_info = ty_to_string ( self ,  ty) ; 
541+                 let  ty_info = ty_to_string ( self ,  ty,   None ) ; 
524542                multi_suggestions. push ( SourceKindMultiSuggestion :: new_closure_return ( 
525543                    ty_info, 
526544                    data, 
@@ -608,6 +626,7 @@ enum InferSourceKind<'tcx> {
608626        insert_span :  Span , 
609627        pattern_name :  Option < Ident > , 
610628        ty :  Ty < ' tcx > , 
629+         def_id :  Option < DefId > , 
611630    } , 
612631    ClosureArg  { 
613632        insert_span :  Span , 
@@ -662,7 +681,7 @@ impl<'tcx> InferSourceKind<'tcx> {
662681                if  ty. is_closure ( )  { 
663682                    ( "closure" ,  closure_as_fn_str ( infcx,  ty) ) 
664683                }  else  if  !ty. is_ty_infer ( )  { 
665-                     ( "normal" ,  ty_to_string ( infcx,  ty) ) 
684+                     ( "normal" ,  ty_to_string ( infcx,  ty,   None ) ) 
666685                }  else  { 
667686                    ( "other" ,  String :: new ( ) ) 
668687                } 
@@ -788,10 +807,18 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> {
788807    /// Uses `fn source_cost` to determine whether this inference source is preferable to 
789808     /// previous sources. We generally prefer earlier sources. 
790809     #[ instrument( level = "debug" ,  skip( self ) ) ]  
791-     fn  update_infer_source ( & mut  self ,  new_source :  InferSource < ' tcx > )  { 
810+     fn  update_infer_source ( & mut  self ,  mut   new_source :  InferSource < ' tcx > )  { 
792811        let  cost = self . source_cost ( & new_source)  + self . attempt ; 
793812        debug ! ( ?cost) ; 
794813        self . attempt  += 1 ; 
814+         if  let  Some ( InferSource  {  kind :  InferSourceKind :: GenericArg  {  def_id :  did,  ..} ,  .. } )  = self . infer_source 
815+             && let  InferSourceKind :: LetBinding  {  ref  ty,  ref  mut  def_id,  ..}  = new_source. kind 
816+             && ty. is_ty_infer ( ) 
817+         { 
818+             // Customize the output so we talk about `let x: Vec<_> = iter.collect();` instead of 
819+             // `let x: _ = iter.collect();`, as this is a very common case. 
820+             * def_id = Some ( did) ; 
821+         } 
795822        if  cost < self . infer_source_cost  { 
796823            self . infer_source_cost  = cost; 
797824            self . infer_source  = Some ( new_source) ; 
@@ -1092,6 +1119,7 @@ impl<'a, 'tcx> Visitor<'tcx> for FindInferSourceVisitor<'a, 'tcx> {
10921119                                insert_span :  local. pat . span . shrink_to_hi ( ) , 
10931120                                pattern_name :  local. pat . simple_ident ( ) , 
10941121                                ty, 
1122+                                 def_id :  None , 
10951123                            } , 
10961124                        } ) 
10971125                    } 
0 commit comments