@@ -10,7 +10,7 @@ use rustc_middle::hir::map::Map;
1010use rustc_middle:: infer:: unify_key:: ConstVariableOriginKind ;
1111use rustc_middle:: ty:: print:: Print ;
1212use rustc_middle:: ty:: subst:: { GenericArg , GenericArgKind } ;
13- use rustc_middle:: ty:: { self , DefIdTree , InferConst , Ty , TyCtxt } ;
13+ use rustc_middle:: ty:: { self , DefIdTree , InferConst , Ty , TyCtxt , TypeFoldable , TypeFolder } ;
1414use rustc_span:: symbol:: kw;
1515use rustc_span:: Span ;
1616use std:: borrow:: Cow ;
@@ -589,6 +589,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
589589 format ! ( "the explicit type `{}`, with the type parameters specified" , ty)
590590 }
591591 Some ( ty) if is_named_and_not_impl_trait ( ty) && ty. to_string ( ) != arg_data. name => {
592+ let ty = ResolvedTypeParamEraser :: new ( self . tcx ) . fold_ty ( ty) ;
593+ let ty = ErrTypeParamEraser ( self . tcx ) . fold_ty ( ty) ;
592594 let ty = ty_to_string ( ty) ;
593595 format ! (
594596 "the explicit type `{}`, where the type parameter `{}` is specified" ,
@@ -868,3 +870,99 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
868870 err
869871 }
870872}
873+
874+ /// Turn resolved type params into `[type error]` to signal we don't want to display them.
875+ struct ResolvedTypeParamEraser < ' tcx > {
876+ tcx : TyCtxt < ' tcx > ,
877+ level : usize ,
878+ }
879+
880+ impl < ' tcx > ResolvedTypeParamEraser < ' tcx > {
881+ fn new ( tcx : TyCtxt < ' tcx > ) -> Self {
882+ ResolvedTypeParamEraser { tcx, level : 0 }
883+ }
884+ }
885+ impl < ' tcx > TypeFolder < ' tcx > for ResolvedTypeParamEraser < ' tcx > {
886+ fn tcx < ' a > ( & ' a self ) -> TyCtxt < ' tcx > {
887+ self . tcx
888+ }
889+ fn fold_ty ( & mut self , t : Ty < ' tcx > ) -> Ty < ' tcx > {
890+ self . level += 1 ;
891+ let t = match t. kind ( ) {
892+ // We'll hide this type only if all its type params are hidden as well.
893+ ty:: Adt ( def, substs) => {
894+ let generics = self . tcx ( ) . generics_of ( def. did ) ;
895+ // Account for params with default values, like `Vec`, where we
896+ // want to show `Vec<T>`, not `Vec<T, _>`. If we replaced that
897+ // subst, then we'd get the incorrect output, so we passthrough.
898+ let substs: Vec < _ > = substs
899+ . iter ( )
900+ . zip ( generics. params . iter ( ) )
901+ . map ( |( subst, param) | match & param. kind {
902+ ty:: GenericParamDefKind :: Type { has_default : true , .. } => subst,
903+ _ => subst. super_fold_with ( self ) ,
904+ } )
905+ . collect ( ) ;
906+ if self . level == 1
907+ || substs. iter ( ) . any ( |subst| match subst. unpack ( ) {
908+ ty:: subst:: GenericArgKind :: Type ( t) => match t. kind ( ) {
909+ ty:: Error ( _) => false ,
910+ _ => true ,
911+ } ,
912+ // Account for `const` params here, otherwise `doesnt_infer.rs`
913+ // shows `_` instead of `Foo<{ _: u32 }>`
914+ ty:: subst:: GenericArgKind :: Const ( _) => true ,
915+ _ => false ,
916+ } )
917+ {
918+ let substs = self . tcx ( ) . intern_substs ( & substs[ ..] ) ;
919+ self . tcx ( ) . mk_ty ( ty:: Adt ( def, substs) )
920+ } else {
921+ self . tcx ( ) . ty_error ( )
922+ }
923+ }
924+ ty:: Ref ( _, ty, _) => {
925+ let ty = self . fold_ty ( ty) ;
926+ match ty. kind ( ) {
927+ // Avoid `&_`, these can be safely presented as `_`.
928+ ty:: Error ( _) => self . tcx ( ) . ty_error ( ) ,
929+ _ => t. super_fold_with ( self ) ,
930+ }
931+ }
932+ // We could account for `()` if we wanted to replace it, but it's assured to be short.
933+ ty:: Tuple ( _)
934+ | ty:: Slice ( _)
935+ | ty:: RawPtr ( _)
936+ | ty:: FnDef ( ..)
937+ | ty:: FnPtr ( _)
938+ | ty:: Opaque ( ..)
939+ | ty:: Projection ( _)
940+ | ty:: Never
941+ | ty:: Array ( ..) => t. super_fold_with ( self ) ,
942+ // We don't want to hide type params that haven't been resolved yet.
943+ // This would be the type that will be written out with the type param
944+ // name in the output.
945+ ty:: Infer ( _) => t,
946+ // We don't want to hide the outermost type, only its type params.
947+ _ if self . level == 1 => t. super_fold_with ( self ) ,
948+ // Hide this type
949+ _ => self . tcx ( ) . ty_error ( ) ,
950+ } ;
951+ self . level -= 1 ;
952+ t
953+ }
954+ }
955+
956+ /// Replace `[type error]` with `ty::Infer(ty::Var)` to display `_`.
957+ struct ErrTypeParamEraser < ' tcx > ( TyCtxt < ' tcx > ) ;
958+ impl < ' tcx > TypeFolder < ' tcx > for ErrTypeParamEraser < ' tcx > {
959+ fn tcx < ' a > ( & ' a self ) -> TyCtxt < ' tcx > {
960+ self . 0
961+ }
962+ fn fold_ty ( & mut self , t : Ty < ' tcx > ) -> Ty < ' tcx > {
963+ match t. kind ( ) {
964+ ty:: Error ( _) => self . tcx ( ) . mk_ty_var ( ty:: TyVid :: from_u32 ( 0 ) ) ,
965+ _ => t. super_fold_with ( self ) ,
966+ }
967+ }
968+ }
0 commit comments