@@ -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
@@ -587,6 +596,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
587596 }
588597 }
589598
599+ let param_type = arg_data. kind . descr ( ) ;
590600 let suffix = match local_visitor. found_node_ty {
591601 Some ( ty) if ty. is_closure ( ) => {
592602 let substs =
@@ -625,15 +635,15 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
625635 }
626636 Some ( ty) if is_named_and_not_impl_trait ( ty) && arg_data. name == "_" => {
627637 let ty = ty_to_string ( ty) ;
628- format ! ( "the explicit type `{}`, with the type parameters specified" , ty)
638+ format ! ( "the explicit type `{}`, with the {} parameters specified" , ty, param_type )
629639 }
630640 Some ( ty) if is_named_and_not_impl_trait ( ty) && ty. to_string ( ) != arg_data. name => {
631641 let ty = ResolvedTypeParamEraser :: new ( self . tcx ) . fold_ty ( ty) ;
632642 let ty = ErrTypeParamEraser ( self . tcx ) . fold_ty ( ty) ;
633643 let ty = ty_to_string ( ty) ;
634644 format ! (
635- "the explicit type `{}`, where the type parameter `{}` is specified" ,
636- ty, arg_data. name,
645+ "the explicit type `{}`, where the {} parameter `{}` is specified" ,
646+ ty, param_type , arg_data. name,
637647 )
638648 }
639649 _ => "a type" . to_string ( ) ,
@@ -910,7 +920,12 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
910920 }
911921}
912922
913- /// Turn resolved type params into `[type error]` to signal we don't want to display them.
923+ /// Turn *resolved* type params into `[type error]` to signal we don't want to display them. After
924+ /// performing that replacement, we'll turn all remaining infer type params to use their name from
925+ /// their definition, and replace all the `[type error]`s back to being infer so they display in
926+ /// the output as `_`. If we didn't go through `[type error]`, we would either show all type params
927+ /// by their name *or* `_`, neither of which is desireable: we want to show all types that we could
928+ /// infer as `_` to reduce verbosity and avoid telling the user about unnecessary type annotations.
914929struct ResolvedTypeParamEraser < ' tcx > {
915930 tcx : TyCtxt < ' tcx > ,
916931 level : usize ,
@@ -920,7 +935,18 @@ impl<'tcx> ResolvedTypeParamEraser<'tcx> {
920935 fn new ( tcx : TyCtxt < ' tcx > ) -> Self {
921936 ResolvedTypeParamEraser { tcx, level : 0 }
922937 }
938+
939+ /// Replace not yet inferred const params with their def name.
940+ fn replace_infers ( & self , c : & ' tcx Const < ' tcx > , index : u32 , name : Symbol ) -> & ' tcx Const < ' tcx > {
941+ match c. val {
942+ ty:: ConstKind :: Infer ( ..) => {
943+ self . tcx ( ) . mk_const_param ( index, name, c. ty )
944+ }
945+ _ => c,
946+ }
947+ }
923948}
949+
924950impl < ' tcx > TypeFolder < ' tcx > for ResolvedTypeParamEraser < ' tcx > {
925951 fn tcx < ' a > ( & ' a self ) -> TyCtxt < ' tcx > {
926952 self . tcx
@@ -940,29 +966,22 @@ impl<'tcx> TypeFolder<'tcx> for ResolvedTypeParamEraser<'tcx> {
940966 . map ( |( subst, param) | match & ( subst. unpack ( ) , & param. kind ) {
941967 ( _, ty:: GenericParamDefKind :: Type { has_default : true , .. } ) => subst,
942968 ( crate :: infer:: GenericArgKind :: Const ( c) , _) => {
943- match c. val {
944- ty:: ConstKind :: Infer ( ..) => {
945- // Replace not yet inferred const params with their def name.
946- self . tcx ( ) . mk_const_param ( param. index , param. name , c. ty ) . into ( )
947- }
948- _ => subst,
949- }
969+ self . replace_infers ( c, param. index , param. name ) . into ( )
950970 }
951971 _ => subst. super_fold_with ( self ) ,
952972 } )
953973 . collect ( ) ;
954- if self . level == 1
955- || substs. iter ( ) . any ( |subst| match subst. unpack ( ) {
956- ty:: subst:: GenericArgKind :: Type ( t) => match t. kind ( ) {
957- ty:: Error ( _) => false ,
958- _ => true ,
959- } ,
960- // Account for `const` params here, otherwise `doesnt_infer.rs`
961- // shows `_` instead of `Foo<{ _: u32 }>`
962- ty:: subst:: GenericArgKind :: Const ( _) => true ,
963- _ => false ,
964- } )
965- {
974+ let should_keep = |subst : & GenericArg < ' _ > | match subst. unpack ( ) {
975+ ty:: subst:: GenericArgKind :: Type ( t) => match t. kind ( ) {
976+ ty:: Error ( _) => false ,
977+ _ => true ,
978+ } ,
979+ // Account for `const` params here, otherwise `doesnt_infer.rs`
980+ // shows `_` instead of `Foo<{ _: u32 }>`
981+ ty:: subst:: GenericArgKind :: Const ( _) => true ,
982+ _ => false ,
983+ } ;
984+ if self . level == 1 || substs. iter ( ) . any ( should_keep) {
966985 let substs = self . tcx ( ) . intern_substs ( & substs[ ..] ) ;
967986 self . tcx ( ) . mk_ty ( ty:: Adt ( def, substs) )
968987 } else {
@@ -986,18 +1005,9 @@ impl<'tcx> TypeFolder<'tcx> for ResolvedTypeParamEraser<'tcx> {
9861005 | ty:: Opaque ( ..)
9871006 | ty:: Projection ( _)
9881007 | ty:: Never => t. super_fold_with ( self ) ,
989- ty:: Array ( ty, c) => {
990- self . tcx ( ) . mk_ty ( ty:: Array (
991- self . fold_ty ( ty) ,
992- match c. val {
993- ty:: ConstKind :: Infer ( ..) => {
994- // Replace not yet inferred const params with their def name.
995- self . tcx ( ) . mk_const_param ( 0 , Symbol :: intern ( "N" ) , c. ty ) . into ( )
996- }
997- _ => c,
998- } ,
999- ) )
1000- }
1008+ ty:: Array ( ty, c) => self
1009+ . tcx ( )
1010+ . mk_ty ( ty:: Array ( self . fold_ty ( ty) , self . replace_infers ( c, 0 , Symbol :: intern ( "N" ) ) ) ) ,
10011011 // We don't want to hide type params that haven't been resolved yet.
10021012 // This would be the type that will be written out with the type param
10031013 // name in the output.
0 commit comments