@@ -11,7 +11,7 @@ use rustc_middle::hir::map::Map;
1111use rustc_middle:: infer:: unify_key:: ConstVariableOriginKind ;
1212use rustc_middle:: ty:: print:: Print ;
1313use rustc_middle:: ty:: subst:: { GenericArg , GenericArgKind } ;
14- use rustc_middle:: ty:: { self , DefIdTree , InferConst , Ty , TyCtxt } ;
14+ use rustc_middle:: ty:: { self , DefIdTree , InferConst , Ty , TyCtxt , TypeFoldable , TypeFolder } ;
1515use rustc_span:: symbol:: kw;
1616use rustc_span:: Span ;
1717use std:: borrow:: Cow ;
@@ -629,6 +629,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
629629 format ! ( "the explicit type `{}`, with the type parameters specified" , ty)
630630 }
631631 Some ( ty) if is_named_and_not_impl_trait ( ty) && ty. to_string ( ) != arg_data. name => {
632+ let ty = ResolvedTypeParamEraser :: new ( self . tcx ) . fold_ty ( ty) ;
633+ let ty = ErrTypeParamEraser ( self . tcx ) . fold_ty ( ty) ;
632634 let ty = ty_to_string ( ty) ;
633635 format ! (
634636 "the explicit type `{}`, where the type parameter `{}` is specified" ,
@@ -908,3 +910,99 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
908910 err
909911 }
910912}
913+
914+ /// Turn resolved type params into `[type error]` to signal we don't want to display them.
915+ struct ResolvedTypeParamEraser < ' tcx > {
916+ tcx : TyCtxt < ' tcx > ,
917+ level : usize ,
918+ }
919+
920+ impl < ' tcx > ResolvedTypeParamEraser < ' tcx > {
921+ fn new ( tcx : TyCtxt < ' tcx > ) -> Self {
922+ ResolvedTypeParamEraser { tcx, level : 0 }
923+ }
924+ }
925+ impl < ' tcx > TypeFolder < ' tcx > for ResolvedTypeParamEraser < ' tcx > {
926+ fn tcx < ' a > ( & ' a self ) -> TyCtxt < ' tcx > {
927+ self . tcx
928+ }
929+ fn fold_ty ( & mut self , t : Ty < ' tcx > ) -> Ty < ' tcx > {
930+ self . level += 1 ;
931+ let t = match t. kind ( ) {
932+ // We'll hide this type only if all its type params are hidden as well.
933+ ty:: Adt ( def, substs) => {
934+ let generics = self . tcx ( ) . generics_of ( def. did ) ;
935+ // Account for params with default values, like `Vec`, where we
936+ // want to show `Vec<T>`, not `Vec<T, _>`. If we replaced that
937+ // subst, then we'd get the incorrect output, so we passthrough.
938+ let substs: Vec < _ > = substs
939+ . iter ( )
940+ . zip ( generics. params . iter ( ) )
941+ . map ( |( subst, param) | match & param. kind {
942+ ty:: GenericParamDefKind :: Type { has_default : true , .. } => subst,
943+ _ => subst. super_fold_with ( self ) ,
944+ } )
945+ . collect ( ) ;
946+ if self . level == 1
947+ || substs. iter ( ) . any ( |subst| match subst. unpack ( ) {
948+ ty:: subst:: GenericArgKind :: Type ( t) => match t. kind ( ) {
949+ ty:: Error ( _) => false ,
950+ _ => true ,
951+ } ,
952+ // Account for `const` params here, otherwise `doesnt_infer.rs`
953+ // shows `_` instead of `Foo<{ _: u32 }>`
954+ ty:: subst:: GenericArgKind :: Const ( _) => true ,
955+ _ => false ,
956+ } )
957+ {
958+ let substs = self . tcx ( ) . intern_substs ( & substs[ ..] ) ;
959+ self . tcx ( ) . mk_ty ( ty:: Adt ( def, substs) )
960+ } else {
961+ self . tcx ( ) . ty_error ( )
962+ }
963+ }
964+ ty:: Ref ( _, ty, _) => {
965+ let ty = self . fold_ty ( ty) ;
966+ match ty. kind ( ) {
967+ // Avoid `&_`, these can be safely presented as `_`.
968+ ty:: Error ( _) => self . tcx ( ) . ty_error ( ) ,
969+ _ => t. super_fold_with ( self ) ,
970+ }
971+ }
972+ // We could account for `()` if we wanted to replace it, but it's assured to be short.
973+ ty:: Tuple ( _)
974+ | ty:: Slice ( _)
975+ | ty:: RawPtr ( _)
976+ | ty:: FnDef ( ..)
977+ | ty:: FnPtr ( _)
978+ | ty:: Opaque ( ..)
979+ | ty:: Projection ( _)
980+ | ty:: Never
981+ | ty:: Array ( ..) => t. super_fold_with ( self ) ,
982+ // We don't want to hide type params that haven't been resolved yet.
983+ // This would be the type that will be written out with the type param
984+ // name in the output.
985+ ty:: Infer ( _) => t,
986+ // We don't want to hide the outermost type, only its type params.
987+ _ if self . level == 1 => t. super_fold_with ( self ) ,
988+ // Hide this type
989+ _ => self . tcx ( ) . ty_error ( ) ,
990+ } ;
991+ self . level -= 1 ;
992+ t
993+ }
994+ }
995+
996+ /// Replace `[type error]` with `ty::Infer(ty::Var)` to display `_`.
997+ struct ErrTypeParamEraser < ' tcx > ( TyCtxt < ' tcx > ) ;
998+ impl < ' tcx > TypeFolder < ' tcx > for ErrTypeParamEraser < ' tcx > {
999+ fn tcx < ' a > ( & ' a self ) -> TyCtxt < ' tcx > {
1000+ self . 0
1001+ }
1002+ fn fold_ty ( & mut self , t : Ty < ' tcx > ) -> Ty < ' tcx > {
1003+ match t. kind ( ) {
1004+ ty:: Error ( _) => self . tcx ( ) . mk_ty_var ( ty:: TyVid :: from_u32 ( 0 ) ) ,
1005+ _ => t. super_fold_with ( self ) ,
1006+ }
1007+ }
1008+ }
0 commit comments