@@ -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 , TypeFoldable , TypeFolder } ;
13+ use rustc_middle:: ty:: { self , Const , DefIdTree , InferConst , Ty , TyCtxt , TypeFoldable , TypeFolder } ;
1414use rustc_span:: symbol:: kw;
1515use rustc_span:: Span ;
1616use std:: borrow:: Cow ;
@@ -305,6 +305,15 @@ pub enum UnderspecifiedArgKind {
305305 Const { is_parameter : bool } ,
306306}
307307
308+ impl UnderspecifiedArgKind {
309+ fn descr ( & self ) -> & ' static str {
310+ match self {
311+ Self :: Type { .. } => "type" ,
312+ Self :: Const { .. } => "const" ,
313+ }
314+ }
315+ }
316+
308317impl InferenceDiagnosticsData {
309318 /// Generate a label for a generic argument which can't be inferred. When not
310319 /// much is known about the argument, `use_diag` may be used to describe the
@@ -548,6 +557,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
548557 }
549558 }
550559
560+ let param_type = arg_data. kind . descr ( ) ;
551561 let suffix = match local_visitor. found_node_ty {
552562 Some ( ty) if ty. is_closure ( ) => {
553563 let substs =
@@ -586,15 +596,15 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
586596 }
587597 Some ( ty) if is_named_and_not_impl_trait ( ty) && arg_data. name == "_" => {
588598 let ty = ty_to_string ( ty) ;
589- format ! ( "the explicit type `{}`, with the type parameters specified" , ty)
599+ format ! ( "the explicit type `{}`, with the {} parameters specified" , ty, param_type )
590600 }
591601 Some ( ty) if is_named_and_not_impl_trait ( ty) && ty. to_string ( ) != arg_data. name => {
592602 let ty = ResolvedTypeParamEraser :: new ( self . tcx ) . fold_ty ( ty) ;
593603 let ty = ErrTypeParamEraser ( self . tcx ) . fold_ty ( ty) ;
594604 let ty = ty_to_string ( ty) ;
595605 format ! (
596- "the explicit type `{}`, where the type parameter `{}` is specified" ,
597- ty, arg_data. name,
606+ "the explicit type `{}`, where the {} parameter `{}` is specified" ,
607+ ty, param_type , arg_data. name,
598608 )
599609 }
600610 _ => "a type" . to_string ( ) ,
@@ -871,7 +881,12 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
871881 }
872882}
873883
874- /// Turn resolved type params into `[type error]` to signal we don't want to display them.
884+ /// Turn *resolved* type params into `[type error]` to signal we don't want to display them. After
885+ /// performing that replacement, we'll turn all remaining infer type params to use their name from
886+ /// their definition, and replace all the `[type error]`s back to being infer so they display in
887+ /// the output as `_`. If we didn't go through `[type error]`, we would either show all type params
888+ /// by their name *or* `_`, neither of which is desireable: we want to show all types that we could
889+ /// infer as `_` to reduce verbosity and avoid telling the user about unnecessary type annotations.
875890struct ResolvedTypeParamEraser < ' tcx > {
876891 tcx : TyCtxt < ' tcx > ,
877892 level : usize ,
@@ -881,7 +896,18 @@ impl<'tcx> ResolvedTypeParamEraser<'tcx> {
881896 fn new ( tcx : TyCtxt < ' tcx > ) -> Self {
882897 ResolvedTypeParamEraser { tcx, level : 0 }
883898 }
899+
900+ /// Replace not yet inferred const params with their def name.
901+ fn replace_infers ( & self , c : & ' tcx Const < ' tcx > , index : u32 , name : Symbol ) -> & ' tcx Const < ' tcx > {
902+ match c. val {
903+ ty:: ConstKind :: Infer ( ..) => {
904+ self . tcx ( ) . mk_const_param ( index, name, c. ty )
905+ }
906+ _ => c,
907+ }
908+ }
884909}
910+
885911impl < ' tcx > TypeFolder < ' tcx > for ResolvedTypeParamEraser < ' tcx > {
886912 fn tcx < ' a > ( & ' a self ) -> TyCtxt < ' tcx > {
887913 self . tcx
@@ -901,29 +927,22 @@ impl<'tcx> TypeFolder<'tcx> for ResolvedTypeParamEraser<'tcx> {
901927 . map ( |( subst, param) | match & ( subst. unpack ( ) , & param. kind ) {
902928 ( _, ty:: GenericParamDefKind :: Type { has_default : true , .. } ) => subst,
903929 ( crate :: infer:: GenericArgKind :: Const ( c) , _) => {
904- match c. val {
905- ty:: ConstKind :: Infer ( ..) => {
906- // Replace not yet inferred const params with their def name.
907- self . tcx ( ) . mk_const_param ( param. index , param. name , c. ty ) . into ( )
908- }
909- _ => subst,
910- }
930+ self . replace_infers ( c, param. index , param. name ) . into ( )
911931 }
912932 _ => subst. super_fold_with ( self ) ,
913933 } )
914934 . collect ( ) ;
915- if self . level == 1
916- || substs. iter ( ) . any ( |subst| match subst. unpack ( ) {
917- ty:: subst:: GenericArgKind :: Type ( t) => match t. kind ( ) {
918- ty:: Error ( _) => false ,
919- _ => true ,
920- } ,
921- // Account for `const` params here, otherwise `doesnt_infer.rs`
922- // shows `_` instead of `Foo<{ _: u32 }>`
923- ty:: subst:: GenericArgKind :: Const ( _) => true ,
924- _ => false ,
925- } )
926- {
935+ let should_keep = |subst : & GenericArg < ' _ > | match subst. unpack ( ) {
936+ ty:: subst:: GenericArgKind :: Type ( t) => match t. kind ( ) {
937+ ty:: Error ( _) => false ,
938+ _ => true ,
939+ } ,
940+ // Account for `const` params here, otherwise `doesnt_infer.rs`
941+ // shows `_` instead of `Foo<{ _: u32 }>`
942+ ty:: subst:: GenericArgKind :: Const ( _) => true ,
943+ _ => false ,
944+ } ;
945+ if self . level == 1 || substs. iter ( ) . any ( should_keep) {
927946 let substs = self . tcx ( ) . intern_substs ( & substs[ ..] ) ;
928947 self . tcx ( ) . mk_ty ( ty:: Adt ( def, substs) )
929948 } else {
@@ -947,18 +966,9 @@ impl<'tcx> TypeFolder<'tcx> for ResolvedTypeParamEraser<'tcx> {
947966 | ty:: Opaque ( ..)
948967 | ty:: Projection ( _)
949968 | ty:: Never => t. super_fold_with ( self ) ,
950- ty:: Array ( ty, c) => {
951- self . tcx ( ) . mk_ty ( ty:: Array (
952- self . fold_ty ( ty) ,
953- match c. val {
954- ty:: ConstKind :: Infer ( ..) => {
955- // Replace not yet inferred const params with their def name.
956- self . tcx ( ) . mk_const_param ( 0 , Symbol :: intern ( "N" ) , c. ty ) . into ( )
957- }
958- _ => c,
959- } ,
960- ) )
961- }
969+ ty:: Array ( ty, c) => self
970+ . tcx ( )
971+ . mk_ty ( ty:: Array ( self . fold_ty ( ty) , self . replace_infers ( c, 0 , Symbol :: intern ( "N" ) ) ) ) ,
962972 // We don't want to hide type params that haven't been resolved yet.
963973 // This would be the type that will be written out with the type param
964974 // name in the output.
0 commit comments