@@ -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 , TypeFoldable , TypeFolder } ;
13
+ use rustc_middle:: ty:: { self , Const , 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 ;
@@ -305,6 +305,15 @@ pub enum UnderspecifiedArgKind {
305
305
Const { is_parameter : bool } ,
306
306
}
307
307
308
+ impl UnderspecifiedArgKind {
309
+ fn descr ( & self ) -> & ' static str {
310
+ match self {
311
+ Self :: Type { .. } => "type" ,
312
+ Self :: Const { .. } => "const" ,
313
+ }
314
+ }
315
+ }
316
+
308
317
impl InferenceDiagnosticsData {
309
318
/// Generate a label for a generic argument which can't be inferred. When not
310
319
/// much is known about the argument, `use_diag` may be used to describe the
@@ -548,6 +557,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
548
557
}
549
558
}
550
559
560
+ let param_type = arg_data. kind . descr ( ) ;
551
561
let suffix = match local_visitor. found_node_ty {
552
562
Some ( ty) if ty. is_closure ( ) => {
553
563
let substs =
@@ -586,15 +596,15 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
586
596
}
587
597
Some ( ty) if is_named_and_not_impl_trait ( ty) && arg_data. name == "_" => {
588
598
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 )
590
600
}
591
601
Some ( ty) if is_named_and_not_impl_trait ( ty) && ty. to_string ( ) != arg_data. name => {
592
602
let ty = ResolvedTypeParamEraser :: new ( self . tcx ) . fold_ty ( ty) ;
593
603
let ty = ErrTypeParamEraser ( self . tcx ) . fold_ty ( ty) ;
594
604
let ty = ty_to_string ( ty) ;
595
605
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,
598
608
)
599
609
}
600
610
_ => "a type" . to_string ( ) ,
@@ -871,7 +881,12 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
871
881
}
872
882
}
873
883
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.
875
890
struct ResolvedTypeParamEraser < ' tcx > {
876
891
tcx : TyCtxt < ' tcx > ,
877
892
level : usize ,
@@ -881,7 +896,18 @@ impl<'tcx> ResolvedTypeParamEraser<'tcx> {
881
896
fn new ( tcx : TyCtxt < ' tcx > ) -> Self {
882
897
ResolvedTypeParamEraser { tcx, level : 0 }
883
898
}
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
+ }
884
909
}
910
+
885
911
impl < ' tcx > TypeFolder < ' tcx > for ResolvedTypeParamEraser < ' tcx > {
886
912
fn tcx < ' a > ( & ' a self ) -> TyCtxt < ' tcx > {
887
913
self . tcx
@@ -901,29 +927,22 @@ impl<'tcx> TypeFolder<'tcx> for ResolvedTypeParamEraser<'tcx> {
901
927
. map ( |( subst, param) | match & ( subst. unpack ( ) , & param. kind ) {
902
928
( _, ty:: GenericParamDefKind :: Type { has_default : true , .. } ) => subst,
903
929
( 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 ( )
911
931
}
912
932
_ => subst. super_fold_with ( self ) ,
913
933
} )
914
934
. 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) {
927
946
let substs = self . tcx ( ) . intern_substs ( & substs[ ..] ) ;
928
947
self . tcx ( ) . mk_ty ( ty:: Adt ( def, substs) )
929
948
} else {
@@ -947,18 +966,9 @@ impl<'tcx> TypeFolder<'tcx> for ResolvedTypeParamEraser<'tcx> {
947
966
| ty:: Opaque ( ..)
948
967
| ty:: Projection ( _)
949
968
| 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" ) ) ) ) ,
962
972
// We don't want to hide type params that haven't been resolved yet.
963
973
// This would be the type that will be written out with the type param
964
974
// name in the output.
0 commit comments