@@ -11,7 +11,7 @@ use rustc_middle::hir::map::Map;
11
11
use rustc_middle:: infer:: unify_key:: ConstVariableOriginKind ;
12
12
use rustc_middle:: ty:: print:: Print ;
13
13
use 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 } ;
15
15
use rustc_span:: symbol:: kw;
16
16
use rustc_span:: Span ;
17
17
use std:: borrow:: Cow ;
@@ -629,6 +629,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
629
629
format ! ( "the explicit type `{}`, with the type parameters specified" , ty)
630
630
}
631
631
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) ;
632
634
let ty = ty_to_string ( ty) ;
633
635
format ! (
634
636
"the explicit type `{}`, where the type parameter `{}` is specified" ,
@@ -908,3 +910,99 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
908
910
err
909
911
}
910
912
}
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