@@ -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
@@ -587,6 +596,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
587
596
}
588
597
}
589
598
599
+ let param_type = arg_data. kind . descr ( ) ;
590
600
let suffix = match local_visitor. found_node_ty {
591
601
Some ( ty) if ty. is_closure ( ) => {
592
602
let substs =
@@ -625,15 +635,15 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
625
635
}
626
636
Some ( ty) if is_named_and_not_impl_trait ( ty) && arg_data. name == "_" => {
627
637
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 )
629
639
}
630
640
Some ( ty) if is_named_and_not_impl_trait ( ty) && ty. to_string ( ) != arg_data. name => {
631
641
let ty = ResolvedTypeParamEraser :: new ( self . tcx ) . fold_ty ( ty) ;
632
642
let ty = ErrTypeParamEraser ( self . tcx ) . fold_ty ( ty) ;
633
643
let ty = ty_to_string ( ty) ;
634
644
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,
637
647
)
638
648
}
639
649
_ => "a type" . to_string ( ) ,
@@ -910,7 +920,12 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
910
920
}
911
921
}
912
922
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.
914
929
struct ResolvedTypeParamEraser < ' tcx > {
915
930
tcx : TyCtxt < ' tcx > ,
916
931
level : usize ,
@@ -920,7 +935,18 @@ impl<'tcx> ResolvedTypeParamEraser<'tcx> {
920
935
fn new ( tcx : TyCtxt < ' tcx > ) -> Self {
921
936
ResolvedTypeParamEraser { tcx, level : 0 }
922
937
}
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
+ }
923
948
}
949
+
924
950
impl < ' tcx > TypeFolder < ' tcx > for ResolvedTypeParamEraser < ' tcx > {
925
951
fn tcx < ' a > ( & ' a self ) -> TyCtxt < ' tcx > {
926
952
self . tcx
@@ -940,29 +966,22 @@ impl<'tcx> TypeFolder<'tcx> for ResolvedTypeParamEraser<'tcx> {
940
966
. map ( |( subst, param) | match & ( subst. unpack ( ) , & param. kind ) {
941
967
( _, ty:: GenericParamDefKind :: Type { has_default : true , .. } ) => subst,
942
968
( 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 ( )
950
970
}
951
971
_ => subst. super_fold_with ( self ) ,
952
972
} )
953
973
. 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) {
966
985
let substs = self . tcx ( ) . intern_substs ( & substs[ ..] ) ;
967
986
self . tcx ( ) . mk_ty ( ty:: Adt ( def, substs) )
968
987
} else {
@@ -986,18 +1005,9 @@ impl<'tcx> TypeFolder<'tcx> for ResolvedTypeParamEraser<'tcx> {
986
1005
| ty:: Opaque ( ..)
987
1006
| ty:: Projection ( _)
988
1007
| 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" ) ) ) ) ,
1001
1011
// We don't want to hide type params that haven't been resolved yet.
1002
1012
// This would be the type that will be written out with the type param
1003
1013
// name in the output.
0 commit comments