@@ -10,7 +10,7 @@ use rustc_middle::hir::map::Map;
10
10
use rustc_middle:: infer:: unify_key:: ConstVariableOriginKind ;
11
11
use rustc_middle:: ty:: print:: Print ;
12
12
use 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 } ;
14
14
use rustc_span:: symbol:: kw;
15
15
use rustc_span:: Span ;
16
16
use std:: borrow:: Cow ;
@@ -589,6 +589,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
589
589
format ! ( "the explicit type `{}`, with the type parameters specified" , ty)
590
590
}
591
591
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) ;
592
594
let ty = ty_to_string ( ty) ;
593
595
format ! (
594
596
"the explicit type `{}`, where the type parameter `{}` is specified" ,
@@ -868,3 +870,99 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
868
870
err
869
871
}
870
872
}
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